Skip to main content
The board saves two graphs. IDs must match across data.nodes, parsedData, trigger, and every edge source / target.

Canvas data (React Flow toObject())

Root nodes:
Sub-nodes are siblings in data.nodes, not nested. They carry parentId:
Edges:
When a node has sub-nodes, do not draw a root out edge from that parent. Execution continues from the sub-node connections.out.

Execution parsedData + trigger

transformReactFlowOutput builds this from the canvas:
  • The trigger is removed from parsedData and stored as workflow.trigger.
  • triggerType is trigger.data.eventType.
  • parsedData is parent nodes only. Sub-nodes hang off parent.subNodes[].
  • Each node has connections: { out: string[] } — target ids only. No handle ids. Branching is “which sub-node’s connections.out”.
  • Runtime starts at trigger.connections.out[0].
Parent title is usually the NodeType string. Sub-node title is the canvas data.label. If/Else matches title.toLowerCase() === "true" / "false".

Mapping checklist

How to wire a graph

Build the canvas first, then copy each edge into execution connections.out. IDs must be identical in data.nodes, data.edges[].source / target, parsedData, trigger, and every connections.out entry.

1. Give every node a stable id

Use short unique strings (trig_1, wa_menu, ans_tours). Reuse the same string everywhere. Sub-nodes live in data.nodes as siblings with parentId set to the parent’s id.

2. Draw canvas edges (data.edges)

Every edge:
Do not also draw a root "out" edge from a parent that has sub-nodes. The engine ignores parent connections.out once subNodes exist and continues from the chosen child’s connections.out.

3. Copy each edge into execution

For every canvas edge source → target, find that source in trigger, parsedData[], or parent.subNodes[] and append target to connections.out (array of target ids only — no handles). Runtime starts at trigger.connections.out[0]. If that array is missing, the run never starts.

4. Sanity check

  • Every source / target / connections.out id exists.
  • Trigger is not in parsedData.
  • Sub-nodes are not extra parsedData items; they hang off parent.subNodes[].
  • Parent with answers / true-false / cases has no root out edge.
Paired snippets: Examples.
Last modified on September 4, 2026