Run a flow & debug failures

Run an .aether flow with Cmd+Enter or F5, watch the graph light up node by node, and trace a failure to the exact request, response and assertion that broke.

8 min read

To run a flow, open its .aether file and press ⌘⏎ or F5. Nodes light up in execution order, the console streams what each one sent and received, and a failure stops on the node that caused it with the expected and actual values side by side. The rest of this page covers the run controls, the debugger, and how to read a failed run.

Running

With an .aether file active, press ⌘⏎, hit F5, or click the brass ▶ Run button in the toolbar. The run uses your full variable stack: the selected environment, .env, flow variables, captures, and any local overrides (how those layer).

You can also run without opening a flow: right-click flows in the File Explorer and choose Run (Cmd/Ctrl-click to select several, Shift-click for a range), or press ▶ on any card in the Flow Map view.

The pre-run guard

If any node references a variable that has no value, the first press of Run doesn’t start a doomed run. It selects the first unresolved node, opens its Variables tab, and relabels the button Run anyway. Fill the value or press again to proceed.

Run from a node

Select a node and press ▶ From here (right edge of the node’s tab strip) to start the run at that node. Everything before it is skipped entirely, so earlier captures and responses simply don’t exist for this run. Useful when you’re iterating on step five of a six-step flow and don’t want to log in every time. The same pre-run guard applies.

The run says what it skipped, in the console before anything executes: the nodes that did not run, named rather than counted, and a warning that this run starts with an empty cookie jar and no cached auth token. Those last two are the ones that catch people out, because nothing in the flow mentions either. A skipped login does not reliably announce itself as a skipped login: it can come back as a 401, a 403, a 200 carrying an empty list, or a capture that fails three nodes later, and every one of those reads as a broken endpoint. If a flow passes end to end but fails from here, read that notice first.

Step through a flow

For a closer look, set breakpoints and walk the run one node at a time:

  • Set a breakpoint by clicking the dot on a node (or right-click the node → toggle breakpoint). The run pauses before that node. Breakpoints are yours alone, stored locally per flow and never written into the .aether file, so they don’t travel in a commit.
  • Start stepping with ⤵ Step in the toolbar: the run begins paused before the very first node. The same pre-run guard applies.
  • While paused, a strip names the node coming up next and offers ▶ Continue (run to the next breakpoint), ⤵ Step (execute just that next node, then pause again), and ◼ Stop.
  • Because the run pauses before a node, the inspector shows its state going in, resolved variables and all, so you can see exactly what it’s about to send.
  • From the keyboard, it’s the bindings you already know: F9 toggles a breakpoint on the selected node, F10 steps, F8 continues.

Stopping a run

While a flow is running, the ▶ Run button becomes ◼ Stop. Press it, or ⇧F5, to cancel: any in-flight HTTP request is aborted, and the run ends as failed with the error cancelled by user; it lands in history like any other failed run.

Watching a run

  • Each node pulses while executing, then takes a green ring (passed) or red ring (failed).
  • Loop nodes carry a live iteration badge (2/5, ticking up as the loop runs) that stays after the run, so you can see how many iterations happened.
  • The Console (bottom panel, ⌘J) logs every step with timestamps; errors are red.
  • The status bar (bottom-right) shows Running…, then Completed or Failed.

Reading the console

  • Lines are grouped by node, so a long run reads as a list of steps rather than one undifferentiated stream. Collapse the ones you have already accounted for.
  • ⌘F searches it once it has focus, and matches are highlighted in place rather than only filtered to.
  • Long output is windowed, not truncated. Past a threshold the console shows a Load more button that raises the window in steps. The same arrangement guards a very large response body in the Result panel. Nothing is silently dropped; you are told there is more and given the button.

Printing from inside a flow

Anywhere a flow runs JavaScript (a script node, a hook, a check/expression/over, a capture expression, a ${{ }} interpolation), you can call log() to print. Lines appear in the Console prefixed │ <nodeId>:, so you can see which step said what.

The point of it is failures: a node that throws still reports what it logged, because lines are flushed after the node settles either way. A log() you added to debug a failure survives the failure. Output is capped at 2 000 characters per line and 200 lines per node; past that the node prints … further log() output from this node suppressed, which is mostly a guard against a log() in a loop body.

The same lines follow the flow everywhere it runs: bandura run prints them dimmed under the node and into <system-out> in JUnit XML, so a CI failure carries the same breadcrumbs you’d see here.

The notification tells you what broke

When a run settles, a notification appears in the corner. A pass is just Run completed. A failure is Run failed plus the actual reason on a second line, because “Run failed” on its own is the one thing you already knew:

What failedWhat the line says
An assertioncheckStatus: response.status was 500, expected === 200
A requestThe node id and the engine’s message, HTTP status included
A network faultThe underlying cause: ECONNREFUSED 127.0.0.1:3000, not a blanket fetch failed
The run itselfCancellation, the whole-run timeout, an unresolvable data set. No node id, because no node failed

Three details that make it usable:

  • It names the first failure, not the last. Everything after the root cause is fallout, and the fallout is what a “last error wins” message would have shown you.
  • A View log button on the notification opens the Console at that run.
  • Repeats collapse. Run the same broken flow three times and you get one row reading Run failed ×3, not three stacked rows. At most four notifications are ever on screen, and hovering one pauses its dismissal timer so a long line can actually be read. Click ✕ to dismiss early.

The line is a summary; long values are truncated. The node’s Result tab has the untruncated version, and for a failed assertion it lays the expected and actual values side by side rather than making you spot the difference in one string.

Nothing that faded is lost. A bell in the corner opens the notifications centre, listing recent notifications including the ones that dismissed themselves, each copyable for a bug report. If you would rather failures never faded at all, set ui.errorToastsPersist to true.

When something fails

Work from the node outward:

  1. Click the red node. Its Result tab in the inspector is the ground truth:
    • Request shows the exact method, URL, headers, and body that were sent, with every ${{ }} already resolved. Wrong URL? Missing header? It’s visible here, not hypothetical.
    • Result has the response status, headers, and body that came back. For a failed assertion, compare the body against your check.
  2. Check the variables it consumed. The node’s Variables tab shows each reference, its source, and its value (with a reveal toggle for masked .env values). A wrong captured value points you at the producing node. Click the captured by badge to jump there.
  3. Check the run-wide picture. The bottom panel’s Variables tab is the full variable snapshot at the end of the run; Console has the sequence of events; History keeps every previous run for comparison (Execution history).
  4. For conditions, the Result tab states which branch was taken and why, so a flow that “skipped” a step usually explains itself in one click.

Try a quick fix without editing anything

Type a value into the override field in a node’s Variables tab and re-run. Overrides take highest precedence and live only on your machine; nothing changes in the file. If the fix deserves to stay, one click promotes it into the flow’s variables: block.

Fixing the flow itself

Edit the node in the inspector’s Node tab (or the Code tab), ⌘S, and run again. If the failure is your API having changed (moved paths, renamed methods, new required params), let self-healing compare the flow against your OpenAPI spec and propose the fixes.

Every run you make is kept, so yesterday’s green run is still there to compare against: see execution history. To run the same flow without the UI, on a schedule or in a pipeline, use the bandura CLI.

Last updated

Looking for something else? All 37 articles are on one page in the Help Center.