/n8n-expression-syntax
Validate n8n expression syntax and fix common errors. Use when writing n8n expressions, using {{}} syntax, accessing $json/$node variables, troubleshooting expression errors, mapping data between nodes, or referencing webhook data in workflows. Use this skill whenever
$ npx -y skills add czlonkowski/n8n-skills --skill n8n-expression-syntax --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/n8n-expression-syntax
Context preview
The summary Claude sees to decide when to auto-load this skill.
Validate n8n expression syntax and fix common errors. Use when writing n8n expressions, using {{}} syntax, accessing $json/$node variables, troubleshooting expression errors, mapping data between nodes, or referencing webhook data in workflows. Use this skill whenever
SKILL.md
n8n-expression-syntax.SKILL.mdname: n8n-expression-syntax
description: Validate n8n expression syntax and fix common errors. Use when writing n8n expressions, using {{}} syntax, accessing $json/$node variables, troubleshooting expression errors, mapping data between nodes, or referencing webhook data in workflows. Use this skill whenever configuring node fields that reference data from previous nodes — expressions are how n8n passes data between nodes, and getting the syntax wrong is the most common source of workflow errors. Also use when asked whether a complex expression hurts performance.n8n Expression Syntax
Expert guide for writing correct n8n expressions in workflows.
---
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)---
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}}**Warning**: Some n8n instances have `N8N_BLOCK_ENV_ACCESS_IN_NODE` enabled, which blocks `$env` access entirely. If `$env` returns errors, use alternative approaches:
- Store values in credentials instead
- Use a Set node with manually entered values
- Pass values through webhook query parameters
---
🚨 CRITICAL: Webhook Data Structure
**Most Common Mistake**: Webhook data is **NOT** at the root!
Webhook Node Output Structure
{
"headers": {...},
"params": {...},
"query": {...},
"body": { // ⚠️ USER DATA IS HERE!
"name": "John",
"email": "john@example.com",
"message": "Hello"
}
}Correct Webhook Data Access
❌ WRONG: {{$json.name}}
❌ WRONG: {{$json.email}}
✅ CORRECT: {{$json.body.name}}
✅ CORRECT: {{$json.body.email}}
✅ CORRECT: {{$json.body.message}}**Why**: Webhook node wraps incoming data under `.body` property to preserve headers, params, and query parameters.
---
Common Patterns
Access Nested Fields
// Simple nesting
{{$json.user.email}}
// Array access
{{$json.data[0].name}}
{{$json.items[0].id}}
// Bracket notation for spaces
{{$json['field name']}}
{{$json['user data']['first name']}}Reference Other Nodes
// Node without spaces
{{$node["Set"].json.value}}
// Node with spaces (common!)
{{$node["HTTP Request"].json.data}}
{{$node["Respond to Webhook"].json.message}}
// Webhook node
{{$node["Webhook"].json.body.email}}Combine Variables
// Concatenation (automatic)
Hello {{$json.body.name}}!
// In URLs
https://api.example.com/users/{{$json.body.user_id}}
// In object properties
{
"name": "={{$json.body.name}}",
"email": "={{$json.body.email}}"
}---
When NOT to Use Expressions
❌ Code Nodes
Code nodes use **direct JavaScript access**, NOT expressions!
// ❌ WRONG in Code node
const email = '={{$json.email}}';
const name = '{{$json.body.name}}';
// ✅ CORRECT in Code node
const email = $json.email;
const name = $json.body.name;
// Or using Code node API
const email = $input.item.json.email;
const allItems = $input.all();❌ Webhook Paths
// ❌ WRONG
path: "{{$json.user_id}}/webhook"
// ✅ CORRECT
path: "user-webhook" // Static paths only❌ Credential Fields
// ❌ WRONG
apiKey: "={{$env.API_KEY}}"
// ✅ CORRECT
Use n8n credential system, not expressions---
The transform gatekeeper
Before you add any node — or write any code — to transform data, walk this order and stop at the first that fits:
1. **Expression** (`{{ ... }}`) in the consuming field. Property access, method chains (`.map().filter().join()`), ternaries, string building, Luxon date math — if it's "take A, produce B" without intermediate variables, it's an expression. This covers most "just transform this" cases. 2. **Arrow-function IIFE inside an Edit Fields field.** When the logic needs intermediate variables, branching, or comments but still operates on one item, wrap it in an immediately-invoked arrow function right in the field value:
={{ (() => {
const items = $json.line_items;
const subtotal = items.reduce((sum, it) => sum + it.price * it.qty, 0);
const tax = subtotal * 0.08;
return (subtotal + tax).toFixed(2);
})() }}The outer `(...)` brackets the function; the trailing `()` invokes it. Drop either and n8n refuses to run. Inside you get the full expression scope (`$json`, `$('Node')`, `$now`, Luxon) plus `const`/`let`, `if`/`switch`, `try`/`catch`, and regex. No `require`, no `await`. 3. **Code node — last resort.** Only when you need multi-item aggregation across the whole dataset (`$input.all()`), an allowlisted library, or async work.
**Why the order matters.** It's not style — it's readability and performance. The Code node runs in a sandboxed VM with per-invocation setup and value marshaling — a cold-start cost that can reach 500–1000ms before your logic runs. (It amortizes on warm, high-item-count runs, so treat this as the common-case cost, not a universal constant.) The same logic in an expression or Edit Fields IIFE runs
Read more
name: n8n-expression-syntax
description: Validate n8n expression syntax and fix common errors. Use when writing n8n expressions, using {{}} syntax, accessing $json/$node variables, troubleshooting expression errors, mapping data between nodes, or referencing webhook data in workflows. Use this skill whenever configuring node fields that reference data from previous nodes — expressions are how n8n passes data between nodes, and getting the syntax wrong is the most common source of workflow errors. Also use when asked whether a complex expression hurts performance.n8n Expression Syntax
Expert guide for writing correct n8n expressions in workflows.
---
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)---
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}}**Warning**: Some n8n instances have `N8N_BLOCK_ENV_ACCESS_IN_NODE` enabled, which blocks `$env` access entirely. If `$env` returns errors, use alternative approaches:
- Store values in credentials instead
- Use a Set node with manually entered values
- Pass values through webhook query parameters
---
🚨 CRITICAL: Webhook Data Structure
**Most Common Mistake**: Webhook data is **NOT** at the root!
Webhook Node Output Structure
{
"headers": {...},
"params": {...},
"query": {...},
"body": { // ⚠️ USER DATA IS HERE!
"name": "John",
"email": "john@example.com",
"message": "Hello"
}
}Correct Webhook Data Access
❌ WRONG: {{$json.name}}
❌ WRONG: {{$json.email}}
✅ CORRECT: {{$json.body.name}}
✅ CORRECT: {{$json.body.email}}
✅ CORRECT: {{$json.body.message}}**Why**: Webhook node wraps incoming data under `.body` property to preserve headers, params, and query parameters.
---
Common Patterns
Access Nested Fields
// Simple nesting
{{$json.user.email}}
// Array access
{{$json.data[0].name}}
{{$json.items[0].id}}
// Bracket notation for spaces
{{$json['field name']}}
{{$json['user data']['first name']}}Reference Other Nodes
// Node without spaces
{{$node["Set"].json.value}}
// Node with spaces (common!)
{{$node["HTTP Request"].json.data}}
{{$node["Respond to Webhook"].json.message}}
// Webhook node
{{$node["Webhook"].json.body.email}}Combine Variables
// Concatenation (automatic)
Hello {{$json.body.name}}!
// In URLs
https://api.example.com/users/{{$json.body.user_id}}
// In object properties
{
"name": "={{$json.body.name}}",
"email": "={{$json.body.email}}"
}---
When NOT to Use Expressions
❌ Code Nodes
Code nodes use **direct JavaScript access**, NOT expressions!
// ❌ WRONG in Code node
const email = '={{$json.email}}';
const name = '{{$json.body.name}}';
// ✅ CORRECT in Code node
const email = $json.email;
const name = $json.body.name;
// Or using Code node API
const email = $input.item.json.email;
const allItems = $input.all();❌ Webhook Paths
// ❌ WRONG
path: "{{$json.user_id}}/webhook"
// ✅ CORRECT
path: "user-webhook" // Static paths only❌ Credential Fields
// ❌ WRONG
apiKey: "={{$env.API_KEY}}"
// ✅ CORRECT
Use n8n credential system, not expressions---
The transform gatekeeper
Before you add any node — or write any code — to transform data, walk this order and stop at the first that fits:
1. **Expression** (`{{ ... }}`) in the consuming field. Property access, method chains (`.map().filter().join()`), ternaries, string building, Luxon date math — if it's "take A, produce B" without intermediate variables, it's an expression. This covers most "just transform this" cases. 2. **Arrow-function IIFE inside an Edit Fields field.** When the logic needs intermediate variables, branching, or comments but still operates on one item, wrap it in an immediately-invoked arrow function right in the field value:
={{ (() => {
const items = $json.line_items;
const subtotal = items.reduce((sum, it) => sum + it.price * it.qty, 0);
const tax = subtotal * 0.08;
return (subtotal + tax).toFixed(2);
})() }}The outer `(...)` brackets the function; the trailing `()` invokes it. Drop either and n8n refuses to run. Inside you get the full expression scope (`$json`, `$('Node')`, `$now`, Luxon) plus `const`/`let`, `if`/`switch`, `try`/`catch`, and regex. No `require`, no `await`. 3. **Code node — last resort.** Only when you need multi-item aggregation across the whole dataset (`$input.all()`), an allowlisted library, or async work.
**Why the order matters.** It's not style — it's readability and performance. The Code node runs in a sandboxed VM with per-invocation setup and value marshaling — a cold-start cost that can reach 500–1000ms before your logic runs. (It amortizes on warm, high-item-count runs, so treat this as the common-case cost, not a universal constant.) The same logic in an expression or Edit Fields IIFE runs
Expert Claude Code skills for building flawless n8n workflows using the n8n-mcp MCP server
Repo: czlonkowski/n8n-skills
Other skills on n8n-mcp-skills.
- /n8n-agents
Design n8n AI agents the right way. Use when building or editing any @n8n/n8n-nodes-langchain.* AI node — an AI Agent, LLM chain, Text Classifier, or Information Extractor — and whenever the user mentions AI agents, LLM with tools, tool calling, $fromAI, system prompts, agent
Open skill - /n8n-binary-and-data
Handle files and binary data in n8n correctly. Use when working with files, images, PDFs, attachments, uploads or downloads, base64, vision/multimodal input, or when an AI agent needs a file as tool input or output — and whenever the user mentions $binary, binaryPropertyName,
Open skill - /n8n-code-javascript
Write JavaScript code in n8n Code nodes. Use when writing JavaScript in n8n, using $input/$json/$node syntax, making HTTP requests with this.helpers / the $helpers global, working with dates using DateTime, troubleshooting Code node errors, choosing between Code node modes, or
Open skill - /n8n-code-python
Write Python code in n8n Code nodes. Use when writing Python in n8n, using _input/_json/_node syntax, working with standard library, or need to understand Python limitations in n8n Code nodes. Use this skill when the user specifically requests Python for an n8n Code node. Note —
Open skill - /n8n-code-tool
Write JavaScript or Python for the n8n Custom Code Tool (@n8n/n8n-nodes-langchain.toolCode) — the AI-agent-callable tool, NOT the workflow Code node. Use when building a Code Tool attached to an AI Agent, writing code that an LLM will invoke, parsing the `query` input, returning
Open skill - /n8n-error-handling
Wire n8n error handling so failures are loud, structured, and recoverable. Use when building any webhook/API workflow, a scheduled or unattended workflow, or any path where a silent failure would drop user-visible work — and whenever the user mentions error handling, onError,
Open skill

