Common failures and how to fix them
Who this is for: anyone whose workflow will not activate, fails in a run, or does not start.
Before you start: note the error code. The app shows it under the message as Error code:, and a failed step’s error ends with the code in square brackets.
Each section below starts with what you see, then explains the cause and the fix. Your AI assistant can help with most of them: ask it to explain the failed run. It calls get_incident, which names the failing step, the last HTTP call and the likely cause.
Secret missing
Section titled “Secret missing”What you see: the workflow will not activate, and the checklist on the Overview tab says Some secrets are missing. Or a run fails and the step’s error ends with [secret_missing]. The codes are secret_missing, secret_requested and secret_expired.
Why: a script or a connection names a secret that has no value. Either nobody created it, it was requested but not filled in yet, it expired, or it was deleted.
How to fix:
- Open Secrets. Secrets that are waiting for a value are listed under Waiting for you.
- Select Add the value and paste it. For an expired secret, select Rotate and paste the new value.
- If the secret is not listed at all, check the name the workflow uses. Names must match exactly, for example
visma_api. Add it with Add a secret, or ask your AI assistant to request it. - Go back to the workflow. The checklist item turns to Done. For a failed run, select Retry from this step.
See Add a secret and Rotate and expire secrets.
Tests failed
Section titled “Tests failed”What you see: activation is refused with tests_failed or tests_not_run. The Tests tab shows cases marked Failed or Can’t run, or the message Some required test cases are missing.
Why: Liitora only activates a version whose tests all pass on that exact version, with the required kinds of cases present:
- a happy path, always;
- an upstream failure, when the workflow calls another system;
- an empty or no-op case, when a step has an
if:or a script can skip; - a malformed payload, when a webhook starts the workflow.
A case also fails when its made-up data looks like a real password or key.
How to fix:
- Open the workflow’s Tests tab. Each check is a sentence with Expected and Actual values.
- Decide what is wrong: the workflow (it does not do what the case says) or the case (it expects the wrong thing).
- Ask your AI assistant to fix it, for example “The test Sends email to IT fails: fix the workflow”. Every save creates a new version and runs the tests again.
- For a missing kind, ask the assistant to add that case.
- For a credential problem, replace the value with an obvious dummy such as
<test-dummy>.
See Read and write workflow tests.
Approval required
Section titled “Approval required”What you see: your AI assistant says the workflow is waiting for approval, and shows an Approve & activate link. Or activation is refused with approval_required. The checklist says A person must approve this version.
Why: by default a person approves each version before it runs in production. AI assistants never approve. The approver needs the Approve workflows permission (admins). You may approve what your assistant made for you. A version you wrote yourself needs another admin (author_cannot_approve), unless you are the only admin and confirm it.
How to fix:
- Open the Approve & activate link, or the workflow and Approve and activate.
- Check What it does, What changed and What the tests check.
- Select Approve this version, then Activate.
- If the buttons are disabled, the page says why, for example “You wrote this version, so someone else needs to approve it.” Ask a colleague with the Approve workflows permission.
See Approve a workflow.
Private address blocked
Section titled “Private address blocked”What you see: a step fails with http_blocked and the message “This address points to a private network, which Liitora can’t reach.” You see the same message from Test connection, a file connection, an alert channel or an email sender whose server is private. The message never shows the address the name resolved to.
Why: Liitora only connects to public internet addresses. This applies to every connection it makes for you: HTTP calls, sign-in with OAuth, file connections (SFTP and S3), alert channels, Microsoft 365 mail and your own SMTP server. It refuses:
- private and internal addresses, such as
10.x.x.x,172.16.x.xto172.31.x.x,192.168.x.x,127.0.0.1and::1; - link-local and cloud metadata addresses such as
169.254.169.254; - names that only exist inside a network:
localhost, names ending in.local,.internal,.lan,.corp,.home.arpa,.svcor.cluster.local, and names without a dot such aserp; - IP addresses written in unusual forms, such as
2130706433or0x7f.1, and IPv6 forms that hide an IPv4 address, such as::ffff:10.0.0.1; - a public name that points to any of these (every address the name resolves to is checked, and Liitora connects only to the address it checked);
- plain
http://, addresses with a user name or password, and redirects to another host.
For a server field that is not a web address (an SMTP or SFTP server), type a host name such as smtp.example.com or a public IP address in the usual dotted form with four numbers.
This protects your network and ours. There is no setting that turns it off.
How to fix:
- Use the system’s public HTTPS address, for example through the API gateway or reverse proxy you already use for partners.
- On the gateway, allow only the paths the workflow needs, and require the API key or sign-in the connection sends.
- If a step calls a full address on another host of the same system (for example a download link the API returns), add that host under Other hosts it may call on the connection. Redirects to another host are never followed: call the final address instead.
- If the system is only reachable inside your network, Liitora cannot reach it yet.
A connection returns 401
Section titled “A connection returns 401”What you see: a step fails with http_status and “The server answered with status 401”. The step’s HTTP calls show 401 (or 403). The connection shows Not working and the hint “The system refused the sign-in”. For OAuth 2 connections the code can be auth_failed.
Why: the other system did not accept the credentials. Common causes: the key or password was changed or revoked on their side, the secret holds the wrong value (for example a space at the end), the key is sent in the wrong header or with the wrong prefix, or the account lacks rights for this call (403).
How to fix:
- Open Connections and select Test connection on the connection. It sends one GET request with the sign-in applied.
- Check the sign-in settings: for an API key, Header or parameter name, Send the key in and Prefix before the key must match what the other system expects.
- Get a fresh key or password from the other system. On Secrets, select Rotate on the secret and paste it.
- For OAuth 2 (authorization code), select Reconnect and sign in again.
- Test again. When it says It works, go to the failed run and select Retry from this step.
See Test a connection.
A connection keeps failing
Section titled “A connection keeps failing”What you see: the connection’s card on Connections says Runs are waiting for this connection. Runs that use it show connection_waiting in their log and wait in the queue. Your admins got a connection_degraded alert.
Why: calls through the connection failed again and again: at least 5 failures, and at least half of the calls, within 5 minutes. A failure is an answer with status 500 or higher, a 429 (too many requests), or no answer at all. Answers like 401, 403 or 404 do not count, because they show that the system is up. Instead of sending more calls to a system that is down, Liitora pauses the runs that use the connection. This works per connection: other connections and other companies are not affected.
What happens next: after 30 seconds one run checks whether the connection works again by making its call. If the call works, every waiting run continues from its last finished step. If not, the next check waits twice as long, up to 10 minutes. Waiting does not use up a run’s attempts. A run that has waited more than 24 hours fails with connection_degraded.
How to fix:
- Check whether the other system is down or overloaded, for example on its status page.
- Open Connections and select Test connection. A test does not wait and does not count towards the check.
- Fix what is wrong on the other system’s side, or the connection’s address. The waiting runs continue by themselves after the next check.
- If a run failed after 24 hours, start it again once the connection works.
Runs wait for a request limit
Section titled “Runs wait for a request limit”What you see: a run’s log says the connection is at its shared request limit or has used its daily request limit, or that the system asked Liitora to wait. The run shows rate_budget_wait and waits in the queue. The connection’s card shows Calls today or The system asked Liitora to wait.
Why: the connection has a shared request limit, and the runs that use it reached it together. Or the other system answered 429 (too many requests) or 503 with a Retry-After time, so every run that uses the connection waits until then, for at most 24 hours. Calls wait their turn instead of failing.
What happens next: a run that waits up to 30 seconds stays in its step. A run that waits longer continues by itself from its last finished step: after the pause the system asked for, after midnight UTC for a daily limit, or within a minute for a per-second limit. Waiting does not use up an attempt.
How to fix:
- Nothing, if the runs can wait. They continue by themselves.
- If the other system allows more calls than you set, raise Calls per second or Calls per day under Edit on the connection. See Set a shared request limit.
- If the daily limit runs out often, make fewer calls, for example by fetching more items per call, or by running a schedule less often.
- If a step times out while it waits, give the step a longer timeout or lower the number of runs that use the connection at the same time.
Quota exceeded
Section titled “Quota exceeded”What you see: an alert quota_exceeded says your company reached its monthly run limit. Production runs stop starting. Earlier you may have seen quota_warning at 80% and 100% of the soft limit.
Why: each plan has a monthly limit of production runs (test runs and dry runs do not count). The month is a calendar month in UTC. When the limit is reached, no new production run starts: scheduled and chained runs are skipped and not made up later, Run now and the API answer run_limit_reached, and webhook senders get 429 quota_exceeded so they can retry later.
How to fix:
- Find what uses the most runs. A schedule such as every 5 minutes makes about 8 600 runs a month.
- Make frequent schedules less frequent, or add
calendar: { skip_on: [weekends] }to skip days nobody needs. See Use calendars and holidays. - Runs start again on the first day of the next month (UTC), or right away when an admin changes the plan.
- If you need a higher limit, ask for a plan change. Use Report a problem in the user menu (top right) in the app.
See Understand usage and limits and Limits per plan.
A webhook returns 401
Section titled “A webhook returns 401”What you see: the sender gets 401 with {"error":{"code":"unauthorized","message":"The webhook was not accepted. Check the URL and how the request is signed."}}, and nothing appears under Recent events.
Why: Liitora gives the same answer for every refusal, so nobody can probe your endpoints. The cause is one of these:
- the URL is wrong or incomplete, or the endpoint was deleted, or it is paused;
- the sender’s address is not in the endpoint’s IP allowlist;
- the signature is missing or wrong: a wrong secret, a secret rotated more than the grace period ago, or a body that changed after it was signed;
- the timestamp is more than 300 seconds off, often because the sender’s clock is wrong or the timestamp is in milliseconds;
- a Stripe endpoint whose secret nobody pasted yet;
- Liitora blocked the endpoint because it was abused (its page says so, with the reason).
How to fix:
- Open Webhooks and select the endpoint. Check that it is On and that the sender uses exactly the URL shown (Copy the URL).
- Run the script from Send a test delivery. If it gets
202, the endpoint works and the problem is in the sender. - Compare the sender’s code with Webhook signing. The page has a test value: with the secret
example-signing-secret, a correct implementation gets the signature shown there. - Sign the raw body bytes exactly as sent. Frameworks that parse and re-encode JSON change the bytes.
- Send the timestamp in whole seconds, and check the sender’s clock.
- If you rotated the secret, update the sender. See Rotate webhook secrets.
If the sender keeps sending refused requests, after 60 in a minute it gets 429 rate_limited instead of 401 until the minute has passed. Fix the cause above, and the answers go back to normal.