The Code node is where n8n stops being a drag-and-drop tool and becomes a programming environment. It is also where most people get stuck, because n8n expects data in one specific shape and the error messages do not always say why a snippet fails. This page collects fifteen JavaScript examples that run as pasted, grouped by the job they do, with the rule that makes each one work.
In short. Every Code node must return an array of objects, each with a json key that holds an object: [{ json: {...} }]. In the default mode ("Run Once for All Items") you read every input with $input.all(). In "Run Once for Each Item" you read the current one with $json. Almost every Code node error comes from breaking one of these two rules.
The one rule: what a Code node must return
n8n passes data between nodes as an array of items. Each item is an object with a json key, and json must itself be an object, not an array or a string. The official documentation lists three errors that all come from this rule: "Code doesn't return items properly", "A 'json' property isn't an object" and "Code doesn't return an object".
If you return the input items unchanged, you already have the right shape, because $input.all() gives you items in that format.
Choose the right mode first
The Code node has two modes, and the variables you can use depend on the mode.
| Mode | When the code runs | How you read data |
|---|---|---|
| Run Once for All Items (default) | Once, whatever the number of items | $input.all(), $input.first(), $input.last() |
| Run Once for Each Item | Once per input item | $json or $input.item.json |
Use "All Items" when you need to compare items, count, group, dedupe or sort. Use "Each Item" when every item is transformed on its own, which keeps the code shorter.
Examples: transform every item
1. Add a field to every item
2. The same thing in "Run Once for Each Item"
3. Keep only some fields
4. Clean and normalise text
Examples: filter, dedupe and sort
5. Filter items
Returning an empty array is allowed. The workflow simply has no items after this node. If later nodes must still run, turn on "Always Output Data" in the node settings.
6. Remove duplicates by email
For duplicates across executions (the same lead arriving twice on different days), use the Remove Duplicates node instead. The n8n documentation recommends it because it can remember values between runs.
7. Sort by a date field
Examples: reshape arrays
8. Split one item holding an array into many items
An API often returns one item such as { orders: [...] }. Most nodes expect one item per order.
The Split Out node does the same thing without code. Use code when you also need to transform each element.
9. Combine many items into one
10. Group and total
Examples: read other nodes and the workflow
11. Read the output of an earlier node by name
$('Node name').all(), .first(), .last() and .item all work in the Code node. The name must match the node title exactly, including spaces.
12. Check that a node ran before reading it
When a workflow has branches, the node you reference may not have run in this execution. Reading it then fails with "Referenced node is unexecuted". The documented guard is isExecuted:
13. Add execution details for logging
Examples: dates and errors
14. Work with dates using Luxon
n8n ships the Luxon library and exposes DateTime and $now in the Code node.
15. Stop the workflow with a clear error
A thrown error stops the execution and, if you set one, starts your error workflow. The message you write is what you will read in the alert, so make it specific.
Debugging a Code node
- Use
console.log()and open your browser developer console while you test. The documentation confirms the Code node writes there. - Test with the real data. Pin the output of the previous node so you can rerun the Code node without calling the API again.
- If the node returns nothing, check the mode.
$jsononly exists in "Run Once for Each Item". - Test the expression parts first with our free n8n Expression Tester, and find the exact path of a nested field with the JSON Path Finder.
When not to use the Code node
The Code node is not the best tool for everything. The n8n documentation itself points to better options for some jobs:
- HTTP calls: use the HTTP Request node. It handles credentials, retries, pagination and batching for you.
- Credentials: Code nodes cannot read stored credentials by design (see our guide to environment variables and credentials in the Code node).
- Simple field mapping: the Edit Fields (Set) node is easier for the next person to read.
- Duplicates across runs: the Remove Duplicates node.
Worked example: clean a lead list before it reaches your CRM
Here is a complete, realistic job that combines several snippets above. A form tool sends leads through an HTTP Request node. Some emails have capitals and spaces, some leads are duplicates, and the CRM rejects records without a company. The Code node fixes all three in one pass, so the CRM node receives only clean, unique, complete records.
- 1 Add a Code node after the node that fetches leads, mode Run Once for All Items.
- 2 Paste the code below.
- 3 Pin the input data, run the node, and compare the input and output counts in the panel.
- 4 Connect the CRM node and map
email,companyandsourcefrom the output.
Why this version holds up in production:
-
?? ''turns missing fields into empty strings, so.trim()never crashes onundefined. - Rejected records are counted and logged instead of silently dropped. If the count jumps one day, you know the form changed.
- The timestamp comes from
$now, the Luxon date n8n provides, so it follows the instance timezone.
If you need the rejected records downstream (for example to email them to someone), return them as well with a flag such as json.valid = false, then split the flow with an IF node. A Code node has one output, so routing is done by the next node.
Performance: when a Code node gets slow
The Code node handles thousands of items comfortably. Slowness usually comes from one of three patterns:
| Pattern | Why it is slow | Faster version |
|---|---|---|
array.find() inside a loop | Scans the whole array for every item | Build a Map once, then map.get(key) |
| Per-item mode on large lists | The code starts once per item | "Run Once for All Items" with one loop |
| Rebuilding big objects with spread in a loop | Copies all fields on every pass | Mutate item.json directly, then return the items |
For very large volumes, process in batches with a Loop Over Items node and keep each Code node run small.
Troubleshooting table
| Symptom | Likely cause | Fix |
|---|---|---|
| "Code doesn't return items properly" | Returned values, not { json } items | return list.map((v) => ({ json: { v } })) |
$json is not defined | Default mode is All Items | Use $input.all(), or switch mode |
items is not defined | Snippet copied from the old Function node | Replace items with $input.all() |
| Next nodes do not run | The code returned [] | Turn on Always Output Data, or handle the empty case |
| "Referenced node is unexecuted" | $('Node') points to a node that did not run | Guard with .isExecuted, or rewire |
| Dates are off by hours | Mixed timezones | Use DateTime with an explicit zone, and check the workflow timezone setting |
Common mistakes to avoid
- Doing in code what a node already does. Filter, Sort, Remove Duplicates, Split Out, Aggregate and Edit Fields cover many jobs, and the next person can read them without JavaScript.
- Hiding business rules in code. If a rule changes often (a price threshold, a list of regions), put it in an Edit Fields node or a custom variable and read it, so nobody has to edit code to change it.
- Swallowing errors. A
try { } catch { }with an empty catch turns a broken API into silent missing data. Throw a clear error, or return the problem as data. - Huge Code nodes. Several small, named Code nodes are easier to debug than one 300-line node.
Production checklist
- The mode chosen on purpose (All Items or Each Item).
- Every return path returns
[{ json: {...} }], including empty cases. - Optional fields read with
?.and??, so one incomplete record does not stop the run. - Errors thrown with a specific message that names the record.
- A sticky note above the node explaining what it does, for the next person.
Frequently asked questions
What is the difference between $json and $input.all() in the n8n Code node?
$json is the current item and only exists in "Run Once for Each Item" mode. $input.all() returns every input item and is what you use in the default "Run Once for All Items" mode.
Can I use import in the n8n Code node?
No. The documentation says import and export are not supported by the sandbox. Use require() instead, and on self-hosted n8n allow the module with NODE_FUNCTION_ALLOW_BUILTIN or NODE_FUNCTION_ALLOW_EXTERNAL. See how to fix "Cannot find module".
Can the Code node return an empty result?
Yes. Returning [] is valid. The next nodes will not run unless you enable "Always Output Data" in the node settings.
Is the Code node slower than built-in nodes?
For normal data volumes the difference does not matter. Python is slower than JavaScript in the Code node, according to the n8n documentation, so prefer JavaScript for large item counts.
How do I loop over items in the n8n Code node?
In "Run Once for All Items" mode, use for (const item of $input.all()) { ... } and return the modified items. In "Run Once for Each Item" mode, n8n does the loop for you and $json is the current item.
Can the Code node make HTTP requests?
The HTTP Request node is the documented way to call APIs: it handles credentials, retries and pagination. Keep the Code node for preparing the data and reading the response.
How do I use dates in the n8n Code node?
n8n includes Luxon. Use DateTime.fromISO() to parse, $now for the current time, .plus() and .diff() for calculations, and .toFormat() to format.
How do I debug a Code node?
Pin the input data, add console.log() lines, open the browser developer console, and run only that node. Check the output panel for the item count and shape.
Tags
Steve founded PURIST, a workflow automation studio working with n8n, Make and Claude AI, and is the point of contact on every project. Prices and features in our articles come from vendor documentation and public pricing pages. How we research and score tools.