Skip to content

Debugging expressions

When an expression doesn't resolve, Flero leaves a marker in the output instead of silently failing. Read the marker, fix the expression, re-run.


The [EXPR-ERROR: …] marker

Every failed expression block is replaced with a marker of the form:

[EXPR-ERROR: <reason>]

The marker uses square brackets, not braces, so downstream evaluators don't re-parse it and silently strip it.

Common reasons:

Marker What it means Fix
Node "X" not found. Available: [A, B, C] Typo or wrong name Copy the exact display name from the canvas
unknown reference "x.output.y" — expected $node["Name"]… You used the shorthand instead of $node["…"] Wrap in $node["x"]
<reason> (anything else) Runtime error during evaluation Read the reason; usually missing field

The marker tells you the available node names for typos. That's deliberate, you can self-correct from the output.


Strategy 1, Click the Data Mapper

The fastest way to write a correct expression is not to type it: click the 🔗 chain icon next to a field. The Data Mapper popover shows a tree of every upstream node's output. Click a leaf, Flero inserts the right $node["…"].json.<path> for you.

The popover also previews the resolved value before you save. If the preview shows what you expected, the expression is correct.


Strategy 2, Run, inspect, iterate

When in doubt:

  1. Run the workflow once (or Test the upstream node) so it has output.
  2. Open the upstream node's inspector → Output panel.
  3. Right-click the field you want → Copy as expression. The clipboard now has {{ $node["Upstream"].json.path.to.field }}.
  4. Paste into the field where you need it.

This is exact, no typos possible.


Strategy 3, Read the [EXPR-ERROR] literally

The marker is designed to be informative. Read every word of the reason text:

  • "Node not found" → typo or out-of-scope reference.
  • "Field not found" → the path navigates into something that didn't exist.
  • "unknown reference" → you forgot the $node["…"] wrapper.
  • Anything else → a runtime exception. Often a type mismatch (calling .toLowerCase() on a number).

Strategy 4, Reduce the expression

For long compound expressions, debug piece-by-piece. Replace the full expression temporarily with just {{ $node["X"].json }} (the whole output) and look at the inspector, is the node returning what you expected? Then add .path.to.field one segment at a time, running each step.


Common pitfalls

Forgetting $node["…"]

// Wrong — looks like a Flero expression but isn't
{{ start.output.x }}

// Right
{{ $node["start"].output.x }}

The evaluator catches this specifically: you'll see [EXPR-ERROR: unknown reference "start.output.x" — expected $node["Name"], $trigger, $workflow, $input, or $env. Did you mean $node["…"].output.field ?].

Case sensitivity

// If the node is named "HTTP Request"
{{ $node["HTTP request"].json.body }}        // ❌ "Node not found"
{{ $node["HTTP Request"].json.body }}        // ✅

Hyphenated names

// Node named "my-fetch"
{{ my-fetch.output.x }}                      // ❌ won't parse
{{ $node["my-fetch"].output.x }}             // ✅

The shorthand-detector only catches names made of \w characters. Hyphenated names must use the $node["…"] form.

Referencing a node that didn't run

If the upstream node is on an If's true branch and the If went false, it has no output. Expressions referencing it fail.

Use an If / Switch in the consuming branch to guard, or move the reference upstream of the branching point.

null substituted as the string "null"

"Hello, {{ $trigger.body.name }}"    // if name is null → "Hello, null"

Use the default-value pattern (Code node or Data Transform) to substitute a fallback.

0 is a valid value, not "missing"

isEmpty on the number 0 is false. If you want "missing or zero", check both: isEmpty OR equal 0.

Confusing $trigger.body and $trigger

$trigger.body is the request body of a webhook trigger. $trigger is the whole trigger payload (body + headers + query + …). Most of the time you want $trigger.body.<field>.


Logging for debug

Drop a Log node mid-workflow with the entire upstream output to see exactly what you're working with:

Message:    DEBUG upstream output: {{ $node["HTTP Request"].json }}
Level:      debug

After the run, open the execution detail and read the resolved message. This is the cheapest way to confirm "what is actually here".


Tips & gotchas

  • [EXPR-ERROR] propagates, if a downstream node receives an expression with the marker baked into a string field, the marker stays as literal text in the output. Treat it as a build-time error, not a runtime warning.
  • The Data Mapper is the cure for 90% of typos. Train yourself to reach for it.
  • When in doubt, log first. Dropping a Log node is faster than guessing.


Found something out of date? This page lives in the Flero docs content set.