- Documentation
- Workflows
- Reference data with expressions
Reference data with expressions
Reference upstream data with the $trigger, $steps, $input, and $meta aliases and JSONata syntax, plus the scope bindings and error codes.
What an expression is
An expression is a small piece of JSONata that you type into a node field to pull a value out of the data your workflow has already produced. When you write $trigger.email into an action's "To" field, TaskJuice evaluates that expression at run time and substitutes the live value.
Expressions are the only way to map data between nodes. You reference upstream output through a fixed set of aliases, each bound to a different slice of the run. The editor highlights aliases as you type, opens an autocomplete dropdown when you type $, and lints the expression inline.
Top-level aliases
These four aliases are available in every expression field. Each binds to a different part of the run context.
| Alias | Binds to | Shape |
|---|---|---|
$trigger | The trigger node's output payload. An alias for the trigger step's output. | Whatever the trigger emits (object) |
$steps | An immutable snapshot of every prior node's output, keyed by node ID. | Object keyed by node ID, each entry { data, meta } |
$input | The current node's input payload. | Object |
$meta | Engine metadata for the run, such as routing decisions and timing. | Object |
The current node's own output data is also available as the implicit root $. An empty expression returns the node's output unchanged, so $ and an empty field behave the same way.
You may see $vars (run-scoped variables) listed in the reference picker as "coming in Stage 4."
It currently binds to an empty object, so any value you read from it will be missing. Do not
depend on $vars in a published workflow.
Reading from $steps
Every node you reference through $steps exposes two keys:
| Key | Holds |
|---|---|
.data | The node's output payload (the values later nodes consume). |
.meta | Engine metadata for that node, such as routing decisions. |
Reference a step by its node ID. When the ID is a plain word (letters, digits, underscores) you can use dot access directly. When the ID contains hyphens or spaces, wrap it in backticks.
$steps.action1.data.result
$steps.action1.data.order.total
$steps.`branch-1`.meta.routingThe node ID is the stable identifier shown in the reference picker, not the display name you see on the canvas. Pick references from the picker to get the exact ID and quoting right.
Scope bindings
Some nodes introduce extra bindings that are only valid inside that node's body. These are lexically scoped: an inner scope shadows an outer one, and referencing a binding outside its node produces an error.
| Binding | Bound inside | Holds |
|---|---|---|
$currentItem | A Loop node's body when its type is "Array Iteration" | The current array element. |
$currentIndex | A Loop node's body when its type is "Array Iteration" | The zero-based index of the current element. |
Inside an array Loop you reference the item you are iterating over with $currentItem and its position with $currentIndex:
$currentItem.email
$currentIndex + 1The expression engine also defines $error (a caught error) and $event (a resumed event
payload), bound inside Try/Catch and Wait-for-Event nodes. Those node types are not in the Add
node panel yet, so you cannot reach $error or $event from the editor. Only the Loop bindings
above are usable today.
JSONata syntax you will use most
JSONata is a full expression language. The pieces that come up most when mapping workflow data:
| Pattern | Example | Result |
|---|---|---|
| Field access | $trigger.customer.email | "ada@example.com" |
| Array projection | $steps.list.data.items.id | An array of every id |
| Array index | $steps.list.data.items[0].id | The first item's id |
| Filter | $steps.list.data.items[status="open"] | Items where status is "open" |
| String join | $trigger.first & " " & $trigger.last | "Ada Lovelace" |
| Conditional | $input.total > 100 ? "high" : "low" | One of the two branches |
| Function call | $uppercase($trigger.code) | The uppercased string |
Expressions can return any type: a string, number, boolean, object, or array. Whatever the expression evaluates to becomes the field's value at run time.
An expression that evaluates to null or undefined fails with NULL_RESULT rather than writing
an empty value. If a field is legitimately optional, guard it: $exists($trigger.note) ? $trigger.note : "".
How the editor helps
The expression editor is a code field with three aids:
- Autocomplete. Type
$to open a dropdown of available references, ranked by scope ($inputfirst, then$trigger,$steps,$vars,$meta). - Reference picker. Open the picker to browse references grouped by scope and insert one without typing. It lists field paths discovered from each upstream node's pinned test output.
- Inline linting. Syntax errors are flagged in place as you type.
The picker only shows the fields it can see. To populate it with real upstream fields, test the upstream node first so its output is pinned. See map data between nodes for the full workflow.
Error codes
When an expression fails, TaskJuice reports one of these codes. Use them to tell a typo apart from a missing upstream value.
| Code | Message | What to check |
|---|---|---|
INVALID_SYNTAX | Expression contains a syntax error and could not be compiled. | A typo in the JSONata: an unclosed bracket, a stray operator, a missing backtick on a hyphenated node ID. |
MISSING_NODE | Referenced step ID not found in execution context. Ensure the referenced step has completed before this step runs. | The node ID in $steps.<id> is wrong, or that node runs after this one rather than before it. |
MISSING_PATH | The referenced step exists but the specified path was not found in its output. | The node ran, but the field you asked for is not in its output. Re-test the upstream node and pick the path from the picker. |
NULL_RESULT | Expression evaluated to null or undefined. | The expression resolved to nothing. Guard optional values with $exists(...). |
EVAL_FAILURE | Expression evaluation failed at runtime. | A runtime problem such as a type mismatch (for example, calling a string function on a number). |
SCOPE_BINDING_OUT_OF_SCOPE | This identifier is not bound at the current cursor position. Move the reference inside the scope-introducing node's body, or remove it. | A scope binding such as $currentItem used outside the Loop node that introduces it. |
Example: a failed reference
Say an action references $steps.action1.data.id, but the upstream node's ID is actually create-contact. The reference compiles cleanly (it is valid JSONata) and then fails at run time with MISSING_NODE, because there is no step keyed action1. The fix is to reference the real ID, with backticks because it contains a hyphen:
$steps.`create-contact`.data.idLimits
- The reference picker reads field paths from pinned test output down to a maximum depth of 5 levels. Fields nested deeper still resolve at run time; they just will not appear as suggestions.
- Branch node conditions are not free-form expressions. The condition
fieldis a JSONata path, but you choose the operator and value from a fixed list in the condition builder. See control flow nodes.
Related
- Map data between nodes walks through wiring upstream output into a field with the picker.
- Control flow nodes covers Branch, Switch, Loop, and Parallel, including where
$currentItemis bound. - Triggers and actions explains how each step's output becomes context for later steps.