13. Troubleshooting¶
Look up the error message directly.
Start here¶
When something goes wrong, go to workflow detail → Overview → execution history and click the failed execution.
- Which node is
FAILED - What input that node received
- What the output of the node right before it looked like
Those three usually reveal the cause.
A
CANCELLEDnode is not the cause. It was merely cleaned up because another node failed. Look at theFAILEDnode.A
SKIPPEDnode is not the cause either. It is simply the branch a conditional did not take, and that is normal.
Errors when saving¶
At save time the graph structure is validated. Expressions are not.
workflow must have exactly one ENTRYPOINT¶
There is no start, or more than one. There has to be exactly one type: ENTRYPOINT node.
only JOINT nodes may have multiple inbound edges¶
Two or more edges lead into one node. Put a JOINT node there and gather them into it.
# ❌ two edges lead into notify
edges:
- from: fetch-a
to: notify
- from: fetch-b
to: notify
# ✅ route them through a JOINT
edges:
- from: fetch-a
to: join
- from: fetch-b
to: join
- from: join
to: notify
cycle detected¶
Following the arrows brings you back to where you started. Find the edge that leads backward and delete it.
If you actually need repetition, use LOOP_START / LOOP_END.
edge references unknown node¶
An id written in an edge's from or to does not exist. Check for a typo in a node id.
duplicate node id¶
Two or more nodes share the same id. Node ids must be unique within a workflow.
condition label has no matching edge¶
Every label on a CONDITIONAL needs exactly one outgoing edge.
execution-info:
conditions:
- label: vip # ← for this label
expression: "${input.amount} >= 100000"
edges:
- from: route
to: vip-handler
label: vip # ← this edge is the match
LOOP_START has no matching LOOP_END¶
The two always come in pairs. Check that execution-info.loop-start on the LOOP_END holds the exact id of the matching LOOP_START.
LOOP_END ... multiple inbound edges (after branching inside a loop)¶
Putting a CONDITIONAL in a loop body is allowed. What you cannot do is wire the branches straight
into LOOP_END — it takes exactly one incoming edge. Reconverge through a JOINT first, then
connect that to LOOP_END.
→ Branching inside a loop
workflow has N nodes — the maximum is 200¶
Split the workflow up. You can chain them by having one workflow call another workflow's webhook with http_request.
It saves, but the slug conflicts¶
That id is already used within the workspace. Change to a different id, or edit the existing workflow.
Errors when running¶
ExpressionResolveException¶
The most common error. The path inside ${...} does not match the actual data.
In this order:
- Look at the actual output of the node right before it in the execution history.
- Compare your expression path against that shape.
- Check for a typo in the node id (
${nodes.fetch-order...}versus the real idfetch-orders).
The usual suspects:
| Wrong expression | The problem |
|---|---|
${nodes.join.response.body.x} |
A JOINT has no output. Reference the node before it |
${nodes.trigger.response.body.windowStart} |
It only exists if the schedule trigger sets lookback |
${secrets.MY_KEY} |
No secret by that name, or you registered it as a plain variable |
${vars.MY_KEY} |
The reverse — you registered a secret and are calling it through vars |
${item.id} |
Unusable outside a loop |
${input.amount} |
The incoming edge has no request.data mapping |
A value arrives as a strange string like {a=1, b=2}¶
You forgot | raw. It is required when passing an array or an object.
→ Details
The Transform node fails¶
A CALL node's output has to be a JSON object. Emitting a bare array or number fails.
expression: "items[*].id" # ❌ array
expression: "{ids: items[*].id}" # ✅ wrap it in an object
expression: "length(items)" # ❌ number
expression: "{count: length(items)}" # ✅
The branch always goes the same way (everything falls to otherwise)¶
There are two causes, and neither of them raises an error.
Cause 1 — the condition does not use ${input.*}. This is the common one.
expression: "${input.amount} >= 100000" # ✅
expression: "amount >= 100000" # ❌ compares the string "amount" to 100000 → always false
eeumsae splits the expression on the operator first, then resolves each side as an expression.
A bare name with no ${...} is not a value — it is that name as literal text.
Cause 2 — the value the condition should see is not handed over. Add request.data to the incoming edge.
Opening the route node's received input in the execution history shows immediately whether the
value arrived.
Slack: not_in_channel¶
You did not invite the bot into the channel. In that channel:
Slack: channel_not_found¶
Either the channel ID is wrong or the channel is private. Find the channel ID in Slack by right-clicking the channel → View channel details → at the bottom. For a private channel, the bot has to be invited before it becomes visible.
Slack: invalid_auth¶
The connection expired or was revoked. Reconnect on the Connections screen.
LLM: 400 Bad Request¶
Two common causes.
temperature— some models, including recent Claude models, do not accept it. Try removing it.- A typo in
model— check that the endpoint knows that model id.
LLM: 401 Unauthorized¶
The API key is wrong or expired. Check the value registered under ${secrets.*}.
Also check that the key matches apiContract — calling ANTHROPIC_MESSAGES with an OpenAI key fails.
It fails with a timeout¶
Raise the timeout value, or narrow the query range.
30s – 2m works well for AI calls, and 30s – 1m for heavy lookup APIs.
The webhook is rejected with 409¶
The workflow is turned off. Flip the toggle on the list or detail screen. While it is off, schedules, webhooks and AI assistant runs are all blocked; only the Run button on screen gets through. → 10. Executions and Monitoring
The webhook is rejected — signature mismatch¶
If a WEBHOOK_SECRET secret exists in the workspace, every webhook requires a signature. The caller
has to attach an X-Webhook-Signature header (or GitHub's X-Hub-Signature-256).
→ 03. Setting Up Triggers
If you never intended to use signatures, check the Variables screen for a secret registered under that name by mistake.
http_request fails on a 3xx¶
The response is a redirect that cannot be followed (no Location header, or 300 / 304).
301, 302, 303, 307 and 308 are followed automatically, so if you hit this, put the final
URL in uri directly.
I narrowed the retries but timeouts are still retried¶
retry-on filters HTTP status and failure kind separately.
Listing only statuses, as in retry-on: ["5xx"], leaves timeouts and connection errors fully retried.
To narrow them, list a failure kind too: retry-on: ["5xx", "connect-error"]
→ 10. Executions and Monitoring
The workflow cannot be edited (MCP)¶
Something is running. Wait for it to finish, or cancel it, and try again.
Frequently asked questions¶
The schedule does not run at the time I want¶
Check timezone. If you omit it you get UTC.
Writing only cron: "0 0 9 * * ?" runs at 6 PM Korea time.
Check that the cron has six fields too. The first one is seconds. → Details
I called the webhook, got a 200, and nothing happened¶
200 means "received, thanks", and the workflow runs asynchronously in the background.
Check the real result in the execution history. Nine times out of ten there is a FAILED sitting there.
A field I sent to the webhook never reaches the next node¶
The trigger's input-schema is a whitelist.
Fields not listed in properties are dropped silently. Add every field you want to use to properties.
I want to pause a schedule for a while¶
Do not delete the workflow — turn it off. The toggle on the list and detail screens switches it, and the cron stops firing while it is off. → 10. Executions and Monitoring
An execution failed and nobody noticed¶
Configure the failure alert webhook on the Notifications screen. → 10. Executions and Monitoring
I'm in the middle of editing a workflow and it won't save¶
The graph structure may not line up yet. The error message tells you what is wrong. Expressions are not checked at save time, so an expression will never be what blocks a save.
The workflow the AI built fails when it runs¶
validate_workflow checks the graph structure only. A wrong ${...} path only shows up when it runs.
Tell the AI to "run it and fix it if it fails" and it will iterate on its own.
If I move to another workspace, do my settings come with me?¶
No. Connections, variables and datasets are per workspace. You have to register them again in the new workspace.
What does it cost?¶
For the terms during the beta, see app.eeumsae.com and the terms of service. AI call costs are separate — eeumsae only makes the call on your behalf with your API key, and the bill comes from OpenAI, Anthropic and the rest directly.
What happens if I edit a workflow while it is running?¶
The shape at the moment the execution started is saved, so an execution already running is unaffected. Your edits apply from the next execution onward.
If it still does not work¶
Get in touch at contact@eeumsae.com. Sending the following along makes it much faster.
- The workflow name or slug
- The time of the failed execution
- The verbatim error message from the execution history
- (If you can) the workflow YAML — with API keys and tokens removed
Back to → Contents