Skip to content

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 CANCELLED node is not the cause. It was merely cleaned up because another node failed. Look at the FAILED node.


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: "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.

CONDITIONAL is not allowed inside a loop body

You cannot put branching inside a loop. → See the alternatives

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:

  1. Look at the actual output of the node right before it in the execution history.
  2. Compare your expression path against that shape.
  3. Check for a typo in the node id (${nodes.fetch-order...} versus the real id fetch-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.

data: "${nodes.fetch.response.body.items}"          # ❌
data: "${nodes.fetch.response.body.items | raw}"    # ✅

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

The value the condition should see is not being handed over. Add request.data to the incoming edge.

edges:
  - from: fetch
    to: route
    request:
      data:
        amount: "${nodes.fetch.response.body.totalAmount}"

And in the condition, use the name alone without ${}: amount >= 100000

Slack: not_in_channel

You did not invite the bot into the channel. In that channel:

/invite @eeumsae

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. 30s2m works well for AI calls, and 30s1m for heavy lookup APIs.

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.

trigger:
  kind: SCHEDULER
  cron: "0 0 9 * * ?"
  timezone: "Asia/Seoul"     # ← required

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.

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 [email protected]. 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 toContents