| name | n8n-expression-syntax |
| description | Writes and debugs n8n node-parameter expressions in {{ }} with $json, $node, $now, and $env. Use when fixing n8n expression errors, webhook field mapping, or Luxon date formatting in parameters. Not for n8n Code-node JavaScript (n8n-code-javascript) or Python (n8n-code-python). |
| version | 1.0.1 |
| risk | unknown |
| source | community |
Overview
Expert guide for writing correct n8n expressions in workflows. All dynamic content in n8n uses double curly braces: {{expression}}.
When to Use
- You need to write or debug n8n expressions using
{{ ... }} syntax.
- The task involves
$json, $node, webhook payloads, or expression-related workflow errors.
- You want syntax-correct dynamic values inside n8n nodes and parameters.
Prerequisites
- Access to an n8n instance or workflow JSON file.
- (Optional) n8n MCP tools for validation.
Procedure
1. Expression Format
All dynamic content in n8n uses double curly braces:
{{expression}}
Examples:
✅ {{$json.email}}
✅ {{$json.body.name}}
✅ {{$node["HTTP Request"].json.data}}
❌ $json.email (no braces - treated as literal text)
❌ {$json.email} (single braces - invalid)
2. Core Variables
$json - Current Node Output
Access data from the current node:
{{$json.fieldName}}
{{$json['field with spaces']}}
{{$json.nested.property}}
{{$json.items[0].name}}
$node - Reference Other Nodes
Access data from any previous node:
{{$node["Node Name"].json.fieldName}}
{{$node["HTTP Request"].json.data}}
{{$node["Webhook"].json.body.email}}
Important:
- Node names must be in quotes
- Node names are case-sensitive
- Must match exact node name from workflow
$now - Current Timestamp
Access current date/time:
{{$now}}
{{$now.toFormat('yyyy-MM-dd')}}
{{$now.toFormat('HH:mm:ss')}}
{{$now.plus({days: 7})}}
$env - Environment Variables
Access environment variables:
{{$env.API_KEY}}
{{$env.DATABASE_URL}}
3. Common Patterns
Access Nested Fields
{{$json.user.email}}
{{$json.data[0].name}}
{{$json.items[0].id}}
{{$json['field name']}}
{{$json['user data']['first name']}}
Combine Variables
Hello {{$json.body.name}}!
https:
{
"name": "={{$json.body.name}}",
"email": "={{$json.body.email}}"
}
4. Advanced Patterns
Conditional Content
{{$json.status === 'active' ? 'Active User' : 'Inactive User'}}
{{$json.email || 'no-email@example.com'}}
Date Manipulation
{{$now.plus({days: 7}).toFormat('yyyy-MM-dd')}}
{{$now.minus({hours: 24}).toISO()}}
{{DateTime.fromISO('2025-12-25').toFormat('MMMM dd, yyyy')}}
String Manipulation
{{$json.email.substring(0, 5)}}
{{$json.message.replace('old', 'new')}}
{{$json.tags.split(',').join(', ')}}
5. Expression Helpers
String:
.toLowerCase(), .toUpperCase()
.trim(), .replace(), .substring()
.split(), .includes()
Array:
.length, .map(), .filter()
.find(), .join(), .slice()
DateTime (Luxon):
.toFormat(), .toISO(), .toLocal()
.plus(), .minus(), .set()
Number:
.toFixed(), .toString()
- Math operations:
+, -, *, /, %
Examples
Webhook, HTTP-to-email, and timestamp examples follow.
Example 1: Webhook to Slack
Webhook receives:
{
"body": {
"name": "John Doe",
"email": "john@example.com",
"message": "Hello!"
}
}
In Slack node text field:
New form submission!
Name: {{$json.body.name}}
Email: {{$json.body.email}}
Message: {{$json.body.message}}
Example 2: HTTP Request to Email
HTTP Request returns:
{
"data": {
"items": [
{"name": "Product 1", "price": 29.99}
]
}
}
In Email node (reference HTTP Request):
Product: {{$node["HTTP Request"].json.data.items[0].name}}
Price: ${{$node["HTTP Request"].json.data.items[0].price}}
Example 3: Format Timestamp
{{$now.toFormat('yyyy-MM-dd')}}
{{$now.toFormat('HH:mm:ss')}}
{{$now.toFormat('yyyy-MM-dd HH:mm')}}
Pitfalls
Use this section when troubleshooting expression errors.
🚨 CRITICAL: Webhook Data Structure
Most Common Mistake: Webhook data is NOT at the root!
Webhook node wraps incoming data under .body property to preserve headers, params, and query parameters.
❌ WRONG: {{$json.name}}
❌ WRONG: {{$json.email}}
✅ CORRECT: {{$json.body.name}}
✅ CORRECT: {{$json.body.email}}
✅ CORRECT: {{$json.body.message}}
When NOT to Use Expressions
Code Nodes
Code nodes use direct JavaScript access, NOT expressions!
const email = '={{$json.email}}';
const name = '{{$json.body.name}}';
const email = $json.email;
const name = $json.body.name;
const email = $input.item.json.email;
const allItems = $input.all();
Webhook Paths
path: "{{$json.user_id}}/webhook"
path: "user-webhook"
Credential Fields
apiKey: "={{$env.API_KEY}}"
Use n8n credential system, not expressions
Validation Rules
- Always Use {{}}: Expressions must be wrapped in double curly braces.
- Use Quotes for Spaces: Field or node names with spaces require bracket notation.
- Match Exact Node Names: Node references are case-sensitive.
- No Nested {{}}: Don't double-wrap expressions.
Quick Fixes
| Mistake | Fix |
|---|
$json.field | {{$json.field}} |
{{$json.field name}} | {{$json['field name']}} |
{{$node.HTTP Request}} | {{$node["HTTP Request"]}} |
{{{$json.field}}} | {{$json.field}} |
{{$json.name}} (webhook) | {{$json.body.name}} |
'={{$json.email}}' (Code node) | $json.email |
Verification
Test in Expression Editor
- Click field with expression
- Open expression editor (click "fx" icon)
- See live preview of result
- Check for errors highlighted in red
Common Error Messages
"Cannot read property 'X' of undefined"
→ Parent object doesn't exist
→ Check your data path
"X is not a function"
→ Trying to call method on non-function
→ Check variable type
Expression shows as literal text
→ Missing {{ }}
→ Add curly braces
Related Skills
- n8n MCP Tools Expert: Learn how to validate expressions using MCP tools
- n8n Workflow Patterns: See expressions in real workflow examples
- n8n Node Configuration: Understand when expressions are needed
Limitations
- Use this skill only when the task clearly matches the scope described above.
- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.