n8n expressions are dynamic, runtime‑evaluated snippets enclosed in
{{ }} that access data from any node, workflow metadata,
environment variables, or built‑in functions. They resolve on every execution,
pulling the latest values from $json, $node, or
$jmespath() without hardcoding fields. The expression system
provides 58+ built‑in methods and variables for string
manipulation, math, date formatting, array handling, and JSON querying. This
guide covers the core variables, Luxon DateTime library, JMESPath querying,
and advanced patterns like $if(), $vars, and
$secrets for reusable automations.
[1]
[2]
| Expression Variable | Description | Example | Code Node? |
|---|---|---|---|
{{ $json.field }} |
Current item field from input | {{ $json.email }} |
✅ (as $input.item.json.field) |
{{ $node["NodeName"].json.field }} |
Data from any previous node | {{ $node["HTTP Request"].json.id }} |
✅ (all(), first(), item) |
{{ $now }} |
Current timestamp (Luxon) | {{ $now.toISO() }} |
✅ (JavaScript only) |
{{ $jmespath($json, "query") }} |
JMESPath JSON query | {{ $jmespath($json, "people[*].name") }} |
✅ (as _jmespath() in Python) |
{{ $vars.myVar }} |
Workflow‑scoped variable (Enterprise/Pro Cloud) | {{ $vars.approvalLimit }} |
✅ |
{{ $secrets.vault.secret }} |
External vault secret (Enterprise) | {{ $secrets.vault.apiKey }} |
✅ |
How do you reference data from other nodes using $json, $node, and $workflow?
Use {{ $json.field }} for the current node’s input item.
To read output from any preceding node, use
{{ $node["Node Name"].json.field }}. The
$workflow object provides metadata like workflow ID, name,
and the active environment. These variables are evaluated dynamically at
execution time by the WorkflowDataProxy class.
[1]
[6]
$node accepts the node’s display name in double quotes and
supports .all(), .first(), .last(),
.item, and .params. For the current node, use
$node.name and $node.type. $workflow
exposes .id, .name, and .active.
For execution context, $execution provides .id
and .mode (test or production). For execution health checks,
$resumeWebhookUrl (deprecated from 1.85.0) can still be
referenced in legacy workflows but should be replaced by the Wait node
with resume URL support. For the complete reference of every
built‑in variable and method available in the expression editor versus
the Code node, see the
Core n8n Nodes guide.
What are the most useful n8n built‑in methods, variables, and data transformation functions?
n8n provides 58+ built‑in methods and variables
spanning string operations ($json.field.length,
.toUpperCase()), math ({{ 1 + 2 }},
Math.round()), boolean logic ({{ true && false }}),
array handling ([1,2,3][0]), and object access
({ a: 1 }.a). All standard JavaScript operators work
inside expressions. The built‑in function
$if(condition, valueIfTrue, valueIfFalse) provides inline
conditional logic without an IF node.
[3]
[1]
Key methods include: $now and $today for date
handling (Luxon objects with full method chains);
$jmespath(object, searchString) for JSON querying;
$if(condition, trueValue, falseValue) for inline
conditionals; $('NodeName').all() and .first()
for node‑specific data access; $itemIndex (0‑based)
and $runIndex for loop tracking; $workflow.name
and $execution.mode for metadata; $render()
and $evaluateExpression() for template rendering;
$('Webhook').params.paramName for webhook URL parameters;
and $now.plus({days: 7}).toFormat('yyyy-MM-dd') for date
arithmetic. All data transformation functions are only available in the
expressions editor—they are not available in the Code node. For the
complete code‑node–only functions, see the
n8n Code Node transformation examples.
$jmespath()) are available in the expression editor
only—not in the Code node. The Code node provides raw
$input.all(), $json, and
$itemIndex for JavaScript/Python logic but must
implement transformations manually.
[3]
How do you extract and transform nested JSON data with JMESPath expressions in n8n?
n8n provides the $jmespath() function to query and filter
JSON using the JMESPath language. The first argument is the target JSON
object (usually $json), and the second is a JMESPath query
string. Syntax: {{ $jmespath($json, "items[?age>`18`].name") }}.
JMESPath supports five projection types—list, slice, object, flatten,
and filter—that handle nested API responses.
[4]
[7]
Important: n8n uses the JMESPath JavaScript library which follows the
search(object, searchString) parameter order—the opposite
of the JMESPath specification’s search(searchString, object).
When adapting examples from official JMESPath documentation, swap the
argument order [4].
For Python users, _jmespath(object, searchString) is
available in the Code node. Common query patterns: extract all names
(people[*].name), filter by age
(people[?age>`18`]), get first item
(people[0]), extract specific fields
(people[*].[name, age]), and count matches
(length(people[?age>`18`])). For direct bracket‑notation
access (e.g., $json['body']['city']), which eliminates
the need for JMESPath for simple field extraction, see the
n8n Webhook Node Configuration guide.
How do you format dates and times using n8n’s Luxon DateTime expressions?
n8n globally exposes the Luxon DateTime library through$now and
$today convenience variables. $now returns the
current timestamp; $today returns midnight of the current
day. Both are Luxon DateTime objects that support the full method chain:
{{ $now.plus({days: 7}).toFormat('yyyy-MM-dd') }}. Parse
strings with DateTime.fromISO('2019-06-23') or
DateTime.fromFormat("23-06-2019", "dd-MM-yyyy").
[5]
[8]
Key Luxon methods available in expressions: toISO(),
toFormat(), toISODate(), plus(),
minus(), diff(), setZone(),
toRelative(), isValid, year,
month, day, hour,
minute, second, weekday,
startOf('month'), endOf('year').
Always use Luxon’s DateTime() rather than vanilla
JavaScript’s Date()—n8n-specific features like
workflow‑specific timezone settings only work with Luxon.
For timezone control, the instance‑levelGENERIC_TIMEZONE and
the workflow‑level Timezone setting determine the reference timezone for
all Luxon operations [8].
For Python Code node users, Luxon convenience variables are available
but with limited functionality—Python equivalents like
datetime.fromtimestamp() should be used for arithmetic.
For comprehensive date‑based conditional logic patterns, such as
checking order age before triggering actions, see the
IF & Switch node branching guide.
{{ $now.toISO() }} → ISO 8601 string.
{{ $now.toFormat('yyyy-MM-dd') }} → custom format.
{{ $now.plus({days: 7, hours: 3}).toISO() }} → date
arithmetic. {{ $now.setZone('America/New_York').toFormat('HH:mm') }}
→ timezone conversion. Always parse strings explicitly with
DateTime.fromFormat() rather than relying on implicit
parsing.
How do you use $vars and $secrets for workflow variables and external vault secrets?
$vars accesses custom variables defined in the
Variables tab (available on Self‑hosted Enterprise and Pro Cloud
plans). Reference with {{ $vars.myVariable }}.
Variables are read‑only during workflow execution and always stored
as strings—n8n replaces the expression with the variable value at
runtime. When a project‑scoped variable shares a key with a global
variable, the project‑scoped value takes precedence.
[9]
[2]
$secrets retrieves secrets from external vault
providers using the syntax
{{ $secrets.<vault-name>.<item-title>.<field-label> }}.
This is an Enterprise plan feature for accessing 1Password, AWS
Secrets Manager, Azure Key Vault, GCP Secret Manager, or HashiCorp
Vault at runtime [2].
Variables accept only alphanumeric characters and underscores (A‑Z,
a‑z, 0‑9, _) with a 50‑character key limit and 1,000‑character
value limit. If a variable has no value, n8n treats it
as undefined—workflows do not automatically fail.
For the complete credential management strategy covering OAuth2
and vault configuration, see the
n8n Credential Nodes guide.
How do you debug n8n expressions and avoid common evaluation errors?
The Expression Editor provides real‑time preview: expand
the editor and click Refresh to see the resolved value against actual
execution data. Auto‑completion surfaces available data paths from
previous node outputs. If an expression returns
[undefined], the referenced field does not exist—use
{{ $if($json.field, $json.field, "N/A") }} for
fallback values. The editor validates syntax and flags errors
before execution [2].
Common pitfalls: mismatched braces (always pair
{{ and }}), undefined fields (use
$if() for fallback), bracket notation for
special characters ($json["field-with-dash"]),
JMESPath argument order reversal (n8n uses
search(object, searchString), not
search(searchString, object)), and accessing
linked item data (use $("NodeName").item instead
of .first() for linked chains). The expression
evaluation pipeline follows a multi‑stage process: WorkflowDataProxy
resolves context variables, then the engine evaluates JavaScript
code, and error handling provides descriptive messages for
debugging. To validate data structure, use the Schema tab in
the output panel or a Code node with console.log().
For the complete error handling and retry patterns that catch
expression‑related failures, see the
n8n Error Handling nodes guide.
References
- DeepWiki — Workflow Data Access and Expression System: WorkflowDataProxy, context variables ($json, $input, $node, $workflow, $execution), evaluation engine
- DeepWiki — Expressions and Variables System: double‑brace syntax, $vars, $secrets, variable scope precedence, expression editor validation (Apr 2026)
- n8n Documentation — Built‑in Methods and Variables: 58+ methods, expression editor vs Code node availability, data transformation functions
- n8n Docs (TeamLab) — Query JSON with JMESPath: $jmespath(object, searchString) syntax, 5 projection types, argument order reversal
- n8n Documentation — Date and Time with Luxon: $now, $today, fromISO(), fromFormat(), toFormat(), timezone configuration
- n8n 中文文档 — Referencing Other Nodes: $json, $node, $input.item, .all(), .first(), .last(), .params access patterns
- n8n 中文文档 — JMESPath Method: $jmespath() and _jmespath() availability, Python Code node support
- n8n Documentation — Luxon Settings: GENERIC_TIMEZONE, Workflow Timezone, vanilla Date() incompatibility with workflow timezone detection
- n8n Documentation — Custom Variables: $vars syntax, project vs global scope precedence, 50‑char key limit, 1,000‑char value limit, available on Enterprise and Pro Cloud
- dev.to — n8n 2.0 AI Agents Architecture: $vars/$secrets distinction, workflow variables for model selection and routing thresholds (2026)
- n8n 中文社区 — Expression Reference: Tournament templating language, JavaScript operations inside {{ }}, error “Expression failed to resolve”

