What to do when…
This page is organised by symptom, not by subsystem: you see something confusing on screen, find it here, read why it happens and move on to the page that explains it in full. Almost every diagnosis comes from one of three places, and it pays to know them in advance:
| Where to look | What it shows | When it helps |
|---|---|---|
| The validation panel in the editor | Graph errors and warnings, each with a code | Before a run: the shape of the graph |
| The Test tab, Debug panel | Rendered templates, input and output of every node | Right after a run: what actually reached the node |
| The Executions section | Status, skip reason, error, credits | After the fact, including other people's turns |
Button and tab names below are quoted as they appear in the product.
An edit changed nothing
What you see: you changed a prompt or a condition, sent a message on the Test tab — and the behaviour is the same as before.
Why: the canvas shows the current board including unsaved edits, but a run executes the last saved version. The graph for a run is taken from a stored workflow version, not from what is drawn on screen — otherwise the same run would mean different things to two browser tabs open on one workflow.
What to do: press Save and try again. If the test looks right but the live chat still answers the old way, that is the second layer of the same thing: the public chat, the widget and every other channel serve the deployed version, not the latest saved one. That needs a deploy.
The deploy button is grey and reads “Up to date”
What you see: on the Deploy tab the button will not press, and it says Up to date instead of Deploy version 7.
Why: there is nothing to deploy — the deployed version equals the current one and no channel setting has changed either. The button also goes grey for a second reason: the selected set of channels is incomplete, so deploying would be meaningless.
| State | What to do |
|---|---|
| It says "Up to date" | Nothing changed. Save a graph edit or change a channel setting — the label turns into a version number. |
| No channel selected | Turn on the switch of at least one channel in the list on the left. |
| Telegram on, no bot picked | Pick a bot in the channel detail — there is nowhere to publish without one. |
| Schedule on, expression empty | Fill in the schedule; an empty field blocks the deploy silently. |
More detail — the Deploy tab.
The deploy was rejected
What you see: a red bar with an error at the bottom of the Deploy tab.
Why: three possible reasons, from three different layers.
① Deploy validation is stricter than the editor’s. Five validation codes are warnings
in the editor and errors on deploy and on every run: exec.multi_exit_race,
exec.no_execution_edges, node.config_invalid, wire.required_port_not_wired,
wire.resource_no_source. That is deliberate: a draft is allowed to be half-finished, a
graph handed to the engine is not. Full list — validation codes.
② The channel is not allowed by your plan. On the free plan you can only deploy to the public chat and the widget; Telegram, webhooks and schedules are paid. The error names the rejected channels.
③ The deployed-workflow limit is reached. The free plan allows one workflow deployed at a time. Undeploy another one — or move to a paid plan.
To find which workflow is holding the slot, look at the workflow list: every workflow shows its version number, and the one holding the slot is the one badged Active — the rest read Draft.
The run was rejected — “Insufficient credits”
What you see: the message will not send; you get an error about credits or about the workspace budget.
Why: the credit balance is at zero. The free plan does not allow work beyond the balance, so the run is refused before the first node rather than halfway through a turn: the platform does not start work it cannot pay for.
Separate from the balance there is the workspace budget — a cap the owner sets on themselves for the period. Its message says how many of the budgeted credits are already spent. The balance may well be non-empty: these are two independent ceilings.
What to do: wait for the next period’s grant, raise the workspace budget (the owner does that), or move to a plan with a larger included allowance.
Where credits go — credits and cost and plan limits.
A node is marked skipped
What you see: in a run, on the Node Executions (12) tab, a node is greyed out. Click it, open the Info tab, read the Why skipped line.
Why: a skip is not a failure. A node runs only if an incoming edge activated it;
everything else is honestly marked skipped, and there are exactly six reasons. The
interface shows a sentence, the API and MCP (get_execution) show a short code. They are
side by side below, because they are the same value:
| Sentence in the interface | Code | What it means and what to do |
|---|---|---|
| An upstream branch went the other way | branch_not_taken | Normal operation: a conditional node took its other leg, a switch matched a different case. Nothing to fix. |
| Every path here died on an upstream failure | upstream_failed | A node above failed and nobody caught the error. Read its error; if the failure is acceptable, draw an on_error branch. |
| Still waiting on inputs: N | unmet_in_degree:N | Some inputs fired, N stayed unresolved. This is a graph defect: usually two independent paths meeting in one node with no barrier. |
| No predecessor of this node ever ran | upstream_not_run | The whole branch above never started. Look for the cause at its head — it will be skipped too. |
| Inside a loop body that never iterated | loop_body_not_entered | The node sits inside a loop or an iteration node whose body never ran: an empty list, or a loop condition false from the start. |
| Nothing could trigger it: no incoming link | no_exec_trigger | The node has no scheduler dependency at all and was never seeded: dropped on the canvas but never wired. |
A seventh value, unknown (“Reason unknown”), is very rare and means the classifier could
not explain the state; keep the link to that run.
Activation is explained in how a graph executes; the status list is in statuses.
The run says “completed” but there is no answer
What you see: a green status, yet the chat is silent or the result is empty.
Why: completed (completed) means “no node failed with an unhandled error” — it
does not mean “the whole graph ran”. An empty answer is never sent to the chat at all:
the platform does not post an empty message and does not write one to history, which is
exactly what “a successful run with no answer” looks like.
Two usual causes:
- The branch that was taken never reached
exit. Findexitin the node list of the run: it will be skipped, with one of the reasons above. Usually a conditional node has one leg going nowhere. exitran and returned nothing. No value arrived at its input — check the output tab of the preceding node.
The shape “exit is unreachable from the entry” is caught before the run and rejected
as the error exec.exit_no_exec_trigger; unreachable nodes that are not exits are the
warning node.not_activated. If a run with that shape still reached the engine, the graph
was saved before the rule existed: press Validate again. Detail —
entry and exit.
A template field came out empty
What you see: a prompt with a hole in it, an HTTP node sending an empty parameter.
Why: an unknown name in a template does not fail the node — it renders as an empty string. That protects a whole turn from dying over one mistyped identifier, and the price is that the typo is invisible.
Where to see it:
- In the editor — the validation panel:
ref.unknown_node(a reference to a node that does not exist) andref.undefined_var(an unknown variable). Both are warnings and do not block saving. - After a run — the Test tab, the
Debugpanel, sectionRendered templates: it shows what actually reached the node, and the key__undefined_refs__lists every path that failed to resolve. That is the only precise trace of a typo.
A common trap: | default(0) substitutes a fallback only for a missing name — but it
does so at any depth, variables.review.score included. What it does not replace is an empty
string that genuinely arrived: for that you need | default(0, true). Full treatment —
templates.
The answer arrives all at once instead of word by word
What you see: a long pause in the chat, then the whole reply at once.
Why: streaming is a separate presentation channel, and not every edge carries it.
| Cause | What to do |
|---|---|
| The edge does not stream | Click the edge from the model to exit: an execute + data + streaming edge has a toggle that turns the streaming channel off. With it off, the reply arrives whole. |
| An ordinary node sits between the model and exit | It rewrites the value, so the tokens would stop matching the answer. A stream only reaches the end through links that are transparent to it. |
| The answer feeds a wait_all barrier | A barrier input is not a streaming port, so by default nothing streams at all. The validator says so with wire.stream_swallowed_by_barrier; pass-through is a barrier option and works when exit follows the barrier directly. |
| Two streams at once | Both land in the same bubble and interleave — the warning wire.concurrent_stream_merge. There is no multiplexing: keep one primary stream. |
Edge types and the toggle — links between nodes.
The Telegram bot is silent in a group
What you see: the bot replies in a direct chat but not in a group, or only to direct mentions.
Why: restrictions on the Telegram side, not the platform’s. By default the Bot API gives a bot in a group only commands, replies to its own messages, and mentions.
What to check, in order:
- Privacy mode in @BotFather. Turn privacy mode off and re-add the bot to the group (remove it and add it again) — otherwise the old restriction stays in force.
- Administrator rights. Part of the surface (moderation, deleting messages) needs admin rights; without them Telegram rejects the calls.
- Update-type subscription. Events not ticked in the received-updates list on the Deploy tab never reach the bot at all — member joins and leaves, for instance.
- Trigger phrases. If a phrase list is set, everything else is ignored on purpose.
The Telegram channel detail has a Check the bot button: it asks Telegram what the bot actually sees and shows the mismatches — privacy mode still on, missing rights, unsubscribed update types, the last webhook error. Start there. Detail — Telegram.
A model disappeared from the list
What you see: a model you were using is missing from a node’s model field.
Why: the lists are filtered strictly, and there are two filters.
- The model’s purpose. A model of your own (an OpenAI-compatible provider integration) carries a purpose — chat, embeddings or rerank. A model marked as embeddings will not appear in an LLM node’s model field, and using it as a chat model fails with “model is declared as embedding”. Check the purpose in the integration — your own models and keys.
- Visibility. Under Settings → Models each model’s visibility is toggled separately; a hidden one is not offered in dropdowns. Models fetched from a provider are off by default — the model catalogue.
The free plan forbids your own models entirely — and not by hiding them afterwards: the provider integration itself will not save, adding it is rejected by the plan.
A run is stuck in the queue
What you see: the status queued (queued) lasts longer than a turn normally takes.
Why: turns of one chat session run strictly one at a time. Until the previous turn finishes, the next one waits — otherwise two turns of one conversation would write to shared memory simultaneously and interleave their events in the stream. This is a normal state, not a fault.
What to do:
- Look at the previous turn of the same session: if it is running, everything is fine. If it is stuck on a slow node, the time ceilings are described in limits and budgets.
- Too many turns piled up in one session are refused up front — you get an error on send, not an endless wait.
- Sends into different sessions run in parallel, but the plan caps how many runs one owner may have at once: on the free plan, one.
Different conversations are different sessions; the run page shows which session a message landed in.
“Internal error. Reference code: …”
What you see: an error with no detail and a long identifier.
That is by design. A third party’s response received on the platform’s key is not shown outside: it says nothing about whether you could have acted differently, and it is very good at dragging extra things into the text — addresses, key fragments, internal class names. So the message has two levels: a meaningful text where the service is yours, and an opaque sentence with a reference code where it is not.
Detail is shown when the service belongs to you: your HTTP request, your database, your workspace integration, your model on your own key. If the model is the platform’s, you will not see its response — quote the reference code to support, it locates the log entry.
What to do: retry if the error looks transient; if it repeats, send the reference code
plus a link to the run. Error codes and the on_error branch —
node errors.
What next
Statuses and skips
What completed, partial and failed actually mean.
Executions
Where to read input, output, error and credits per node.
Validation codes
Every check and what it means.
How a graph executes
Why a node runs — or does not.
Node errors
The on_error branch, codes and retries.
Your first chatbot
Walk the whole path again on a small example.