Skip to main content

Flow troubleshooting

A source-backed debugging sequence for ActionFlow validation, queueing, execution, webhooks, and human approvals.

Flow troubleshooting

Use this sequence from the outside in. It separates a trigger/admission problem from a graph or node problem and avoids changing code before the saved graph is known to be the graph that ran.

Record the run ID, queue ID, trigger source, timestamp, and failing node ID before changing the graph. Never paste credentials, signed URLs, callback secrets, or sensitive request bodies into a ticket or chat message.

1. Identify the trigger source

Start with the origin, not with the last node:

  • Actionflow Studio and dashboard runs are recorded as manual.
  • API-key runs are recorded as api unless the caller supplied another source.
  • Inbound flow webhook runs are recorded as webhook.
  • Scheduled runs use schedule; a subflow-shaped start uses subflow when a caller supplies that source.
  • An unrecognized or missing source is shown as unknown in the app.

For a webhook or API request, save the response's runId and queueId, the request time, and any idempotency key you control. A 202 response only means the request was accepted or placed in the queue.

2. Inspect the saved graph

External execution reads the ActionFlow's saved nodes and edges. In Actionflow Studio, use the save/run path rather than relying on an unsaved canvas state: Actionflow Studio explicitly saves before starting a run. Check:

  • exactly one supported start node is present;
  • the start node has an outgoing connection when non-start nodes exist; for the start-chain validation check, any outgoing edge counts, regardless of handle semantics;
  • the nodes you expect to run are reachable from that start;
  • control lanes and Loop body edges have the expected handles;
  • no stale node, renamed input, or disconnected branch is left in the saved JSON.

Run history stores execution metadata, not a complete immutable graph snapshot. If the graph was edited after the run, compare the current saved graph with the event and node IDs in the history row.

3. Run validateFlow

validateFlow is used at different points by different ingress paths:

  • Actionflow Studio runs, dashboard/API runs, reruns, and webhooks validate the saved graph before enqueue. API and webhook validation runs before the caller's inputs are merged into the execution copy.
  • Scheduled ticks and queue-dispatched continuations can be admitted and receive a history row first. The queue consumer validates queued items later, and direct dispatch does not have the same pre-enqueue check. A queued run can therefore be failed for validation after a row exists, while a direct scheduled run can fail later during execution.

validateFlow checks:

  1. nodes and edges are arrays and graph entries have the required structure.
  2. A start node exists and has a supported outgoing chain when the graph has non-start nodes.
  3. Reachable nodes are enabled.
  4. Reachable integration/HITL nodes have usable organization connections.
  5. Reachable AI nodes have a valid platform or BYOK service/model selection.
  6. Required inputs are saved or connected to the required named handle. Run inputs are not a universal substitute for validation.
  7. Reachable Loop configuration is valid.

Unreachable nodes are not validated as part of the executable subgraph. A warning is not the same as a blocking validation error. Actionflow Studio's Flow Requirements is a focused missing-connection view; it is not a complete replacement for the validation result returned to API and webhook callers.

4. Check reachable-node requirements

Fix the smallest failing node first. For each reachable node, verify:

  • the node category and integration are enabled;
  • a required named input has a static value or a matching data handle; a {nodeId}_{inputName} run input is an ingress-specific execution value and is not a substitute for API/webhook pre-enqueue validation;
  • a node-target edge is not being mistaken for a named input connection;
  • an AI node has the intended model and credentials mode;
  • an integration node has the selected organization connection when multiple connections exist;
  • a Loop has an array or valid JSON array and its output mode is valid.

For Loop nodes, distinguish manual items from an inherited reference. Manual mode accepts an array or a JSON array string. Inherited mode must contain one exact node-output reference that resolves to an actual array; a single object or a JSON string containing an array is invalid. Also check the Loop output mode: outputAsObject: true (the seeded default) exposes the current item inside {{loopNodeId.iteration}}, while outputAsObject: false exposes it through {{loopNodeId.item}}. {{loopNodeId.result}} and its nested paths expose the aggregate result regardless of output mode.

Disconnected nodes can remain on the canvas without blocking validation, but they also will not run.

5. Inspect credentials, model, and input values

Check configuration without copying secrets:

  • Confirm the organization connection exists and the node references the intended connection.
  • Confirm OAuth scopes/tokens and API-key-backed services are usable in the organization context.
  • For AI nodes, distinguish a platform model from an organization BYOK model.
  • For Actionflow Studio runs, compare the run form's keys with the empty required fields shown by Flow inputs. For API and webhook ingress, a run input is merged after saved-graph validation, so a blank saved field can still fail validation.
  • Inspect mappings such as {{nodeId.outputPath}} and verify that the referenced node is reachable and the path exists.

A missing placeholder path can become an empty string or undefined value without producing a graph validation error. A placeholder reference can also call executeNode for a reachable referenced node and run downstream side effects before the normal traversal reaches them. Add an explicit execution edge when ordering or side-effect control matters. The downstream node may then fail, or may intentionally handle an empty value.

6. Check the run and queue

Follow the identifier returned by the trigger:

  • dispatched/QUEUED means the execution service accepted the run; it is not a completion signal.
  • waiting means it is still in the organization queue. Poll the queue item and use its queueId; a waiting item can be cancelled.
  • dispatching is a short handoff state between the queue and execution.
  • executing means the graph is running. Use the run stream or run history to follow node progress.
  • A terminal completed, failed, or cancelled state is the point to inspect persisted results.

If a run is waiting longer than expected, check queue position and queue status before changing the graph. For a queued run, validation can happen after admission, so a run-history row may already exist when validateFlow fails. A direct scheduled run can instead fail during execution because it does not share the API/webhook pre-enqueue check. The public queue response is an object containing items and total; see the Queue API for the current filters and page-size contract.

7. Inspect the failing node and its result

Open the run history detail and inspect:

  • the run error or the last node event;
  • the node ID, node type, and input mapping;
  • whether the node returned success: false or threw an exception;
  • the results of nodes that completed before the failure;
  • credit usage and any organization-credit error.

A node result can be empty for a valid reason, such as a provider returning 204, an empty response body, null, or a function intentionally returning no value. It can also look empty because a path was missing or because the history read path filtered the payload. Check the live Actionflow Studio output and the exact node before treating an empty result as a data-loss bug.

Symptoms and responses

SymptomWhat it meansWhat to do
Passive Flow: 409The webhook found the flow but its active flag is false.Open Settings and activate the flow when it is ready for external execution. Passive does not prevent graph editing or Actionflow Studio testing.
API/Actionflow Studio passive runThe current runActionFlow path does not perform the webhook-style active-state check.Do not expect a 409 from the API/Actionflow Studio run path. Treat activation as required for webhook and scheduled triggers, not as a general execution lock.
Webhook: 403The webhook record exists but is disabled.Enable the webhook in the flow's Webhooks settings. This is different from a passive flow, which returns 409.
Webhook: 409The flow is passive.Activate it, then retry the delivery. The request is rejected before enqueue.
Webhook: 422validateFlow rejected the saved graph before the webhook input envelope was merged.Read the returned validation errors, fix the reachable node/connection/input, save the graph, and retry. No run is enqueued.
Webhook: 202The webhook was accepted and a run was dispatched or queued.Save runId/queueId, then inspect queue or run history. It is not proof that the nodes completed.
API: 400The request body failed schema validation, or the saved flow failed validateFlow.Distinguish request issues from validationErrors/validationWarnings; fix the body or reachable graph accordingly.
Queued validation failureThe queue consumer rejected the run after the queue/history row had already been created.Inspect the history row and queue/worker result; do not assume that a row implies validateFlow passed.
Scheduled invalid graphThe scheduler enqueues an active scheduled flow without the API/webhook pre-enqueue validation.Inspect the run's execution failure; the history row is not proof that validateFlow passed.
Queue: 202The API accepted a queued run.Poll the queue item and watch for dispatched, failed, or cancelled; do not rerun immediately just because it is still waiting.
Failed nodeA node threw, returned success: false, or the run exhausted an execution/credit condition.Inspect the node event and partial results, then correct the input, mapping, credential, model, or provider response. continueOnError only changes reported output failures.
Empty outputThe result is null/empty, a path resolved to nothing, or the persisted view filtered the result.Check the node's raw live output, response status/body, mapping path, and the history sanitizer before changing the graph.
Unexpected placeholder side effectResolving a reachable reference called executeNode and ran downstream work earlier than the explicit graph order.Add the intended execution edge and retest; do not use a placeholder as a side-effect-free lookup when order matters.
Loop has the wrong items or output shapeThe inherited reference was not an array, or the placeholder root does not match outputAsObject.Resolve the Loop reference to an array and use {{loopNodeId.iteration}} when outputAsObject is true; use {{loopNodeId.item}} when it is false.
HITL waitingThe run reached a HITL node and is waiting for a human decision.Open Approvals or the flow's pending request, then approve, edit, or reject before the callback expires. The downstream continuation is a new run, not an automatic timeout branch.
HITL callback: 202 with resolved: falseThe request was accepted, but the decision could not be resolved, the required comment was missing, or the continuation enqueue failed.Check resolved, then inspect the pending request and prefix/continuation history; the callback response does not include a continuation ID or enqueue error.

A safe retry path

After fixing a graph or input problem:

  1. Save the intended graph.
  2. Re-run validateFlow directly when the surface exposes that result; for queued runs, inspect queue-time validation, and for direct scheduled runs, inspect the execution result.
  3. Start a new run with known test inputs.
  4. Follow the returned run or queue ID.
  5. Inspect the terminal result and credit usage before scaling the trigger.

Use Rerun only when the product offers it for the history row. A rerun is a new execution from the current saved graph and can repeat external side effects; it is not a checkpoint resume. See Run history.

On this page