# n8n Code node: JavaScript, Python, item modes and common errors

> The n8n Code node runs your own JavaScript or Python as a workflow step. In the default mode, Run Once for All Items, your code runs once over every input item, while the each-item mode runs it once per item. Either way it must return items as objects with a json key, and it cannot make HTTP requests, read files or use credentials.

Mindket editors · Published 2026-11-04 · Updated 2026-11-05 · https://mindket.com/learn/n8n-advanced/n8n-code-node

## In short

- Pick Run Once for All Items or Run Once for Each Item and return the right shape from each.
- Read input with $input, $json and $('Node name') inside the node.
- Keep item linking intact with pairedItem when you create new items.
- Know what the node cannot do and read its common errors.

## Before you start

The Code node changed a good deal across the 2026 releases, so check your version first. The [docs](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.code) say it replaced the Function and Function Item nodes from n8n 0.198.0. n8n 3.0, in early access since 27 October 2026, removes those legacy nodes. The [breaking-changes page](https://docs.n8n.io/changelog/v30-breaking-changes) maps them across: **Run Once for All Items** replaces Function and **Run Once for Each Item** replaces Function Item. The same release removes the Ask AI tab, and code it generated earlier stays and keeps running.

Python moved too. n8n 2.0 removed the Pyodide version, and native Python on task runners arrived in n8n 1.111.0 and is stable as of n8n 2. The samples here are our own, written from the variable names and item shape in the docs.

## Write your first Code node

Every item that leaves the node is an object with a `json` key. The sample below builds new items from the `name` field of each input item and sets `pairedItem`, which a later section explains:

````javascript
// Mode: Run Once for All Items
const rows = $input.all();
const out = [];
for (let i = 0; i < rows.length; i++) {
  out.push({
    json: { name: rows[i].json.name, nameLength: rows[i].json.name.length },
    pairedItem: i,
  });
}
return out;
````

1. Add a **Code** node after a node that outputs items with a `name` field, such as an Edit Fields node.
2. Set **Language** to **JavaScript** and **Mode** to **Run Once for All Items**, which is the default.
3. Paste the sample into the code editor.
4. Select **Execute step**. The output should hold one item per input item, each with `name` and `nameLength`.
5. Add `console.log(rows.length)` above the return, run the node again and open your browser's developer console. The [cookbook page](https://docs.n8n.io/build/code-in-n8n/cookbook/code-node/output-to-the-browser-console) says `console.log()` in the Code node writes there.

## Two modes, two return shapes

n8n passes data between nodes as an array of objects, each wrapping its data in a `json` key. The [data structure page](https://docs.n8n.io/build/work-with-data/understand-n8ns-data-structure) adds that from n8n 0.166.0 the Code node supplies a missing `json` key and the array wrapper for you, so a plain object works too. Spelling both out keeps your code honest about what it returns.

The JavaScript task runner's [source](https://github.com/n8n-io/n8n/blob/master/packages/@n8n/task-runner/src/js-task-runner/js-task-runner.ts) settles what each mode accepts. Run Once for Each Item runs the code once per input item and expects one item back. Returning `null` skips that item, and n8n sets `pairedItem` to the current index for you. This is the each-item version of the sample above:

````javascript
// Mode: Run Once for Each Item
return { json: { name: $json.name, nameLength: $json.name.length } };
````

| Aspect | Run Once for All Items | Run Once for Each Item |
| --- | --- | --- |
| How often the code runs | Once, however many input items arrive | Once for every input item |
| Read input with | `$input.all()`, `$input.first()`, `$input.last()` | `$input.item` or `$json` |
| Return | An array of items | One item |
| Returning `null` | No items come out | That item is skipped |
| Item linking | You set `pairedItem` on new items | n8n sets `pairedItem` to the current index |

## Reading data from the input and from other nodes

The [reference page](https://docs.n8n.io/build/work-with-data/reference-data/reference-previous-nodes) lists what works in the Code node. Type `$` in the editor and n8n suggests the rest. Binary data has its own rule: `$binary` is not available here, so call `this.helpers.getBinaryDataBuffer(itemIndex, binaryPropertyName)`, which the [cookbook page](https://docs.n8n.io/build/code-in-n8n/cookbook/code-node/get-the-binary-data-buffer) prefers to reaching into `items[0].binary.data.data`. It is not supported in Python.

One trap sits between the expressions editor and the Code node. The Code node runs plain JavaScript against native Luxon, not n8n's expression engine, and the [shortcuts page](https://docs.n8n.io/build/code-in-n8n/use-built-in-shortcuts) says what follows.

> **Native Luxon, no n8n extras**
>
> Anything tagged Custom n8n functionality in the expressions reference may be missing here. DateTime.format() is one, so use toFormat(). The top-level helpers such as $if() and $jmespath() work only in the expressions editor. DateTime.plus() and minus() take one Duration-like object, such as { days: 7 }, and the expression-style (amount, unit) form does not error but gives the wrong result.

| Expression | What you get |
| --- | --- |
| `$input.all()` | Every input item |
| `$input.first()`, `$input.last()` | The first or last input item |
| `$input.item` | The item being processed |
| `$json` | Shorthand for `$input.item.json`, available when running once for each item |
| `$('Node name').all()`, `.first()`, `.last()` | Items from another node, with optional `branchIndex` and `runIndex` arguments |
| `$('Node name').item` | The item in that node that produced the current one |
| `$('Node name').itemMatching(i)` | Use it in place of `.item` when you trace back from an input item |
| `$input.context.noItemsLeft` | A boolean that exists only with Loop Over Items |

## Python in the Code node

Set **Language** to **Python** and you get native Python from task runners. The [docs](https://docs.n8n.io/build/code-in-n8n/using-the-code-node) call the move from Pyodide a breaking change, so old scripts may need edits. The same sample in native Python:

````python
# Mode: Run Once for All Items, native Python
rows = []
for item in _items:
    rows.append({"json": {"name": item["json"]["name"]}})
return rows
````

- Only `_items` in all-items mode and `_item` in each-item mode exist. The other n8n built-in methods and variables are not supported.
- Fields need bracket access, as in `item["json"]["my_new_field"]`. The dot form `item.json.myNewField` is not accepted.
- On self-hosted n8n, imports work only for standard library and third-party modules that the `n8nio/runners` image includes and allowlists. On n8n Cloud, no imports are allowed.
- Insecure built-ins are denied by default, and `type()` is on the list. Use `print(_items)` to inspect data instead.

## Keep item linking intact

Most nodes link each output item to the input item that produced it, and later nodes follow that chain with `$('Node name').item`. In the Code node n8n handles linking for a single item. With more than one incoming item you supply it yourself when you [add or return new items](https://docs.n8n.io/build/work-with-data/reference-data/link-data-items/preserving-linking-in-the-code-node), by setting `pairedItem` to the index of the input item. That is why the first sample carried `pairedItem: i`.

Going back is the job of `itemMatching`. This is the [docs' example](https://docs.n8n.io/build/work-with-data/reference-data/link-data-items/accessing-linked-items-in-the-code-node), which restores an email address that an Edit Fields node had dropped:

````javascript
for(let i=0; i<$input.all().length; i++) {
	$input.all()[i].json.restoreEmail = $('Customer Datastore (n8n training)').itemMatching(i).json.email;
}
return $input.all();
````

## What the Code node cannot do

Task runners execute the code. The [docs](https://docs.n8n.io/deploy/host-n8n/configure-n8n/set-up-task-runners) call them the only isolation layer between user-provided code and n8n, say internal mode is deprecated and point production instances at external mode, with a runners container beside n8n. The [self-hosting lesson](https://mindket.com/learn/n8n/self-host-n8n-docker) covers the Docker side.

The timeout changed too. The [task runner variables page](https://docs.n8n.io/deploy/host-n8n/configure-n8n/basic-configuration/use-environment-variables/task-runners) still lists a default of 300 seconds for `N8N_RUNNERS_TASK_TIMEOUT`. The breaking changes drop it to 60, so a longer task fails unless you set the variable yourself.

**Three numbers behind these limits**

- **60** seconds a Code node task may run in n8n 3.0 before it fails, down from 300 (Source: [n8n Docs: v3.0 breaking changes](https://docs.n8n.io/changelog/v30-breaking-changes), read 2026-11-05)
- **2** modules n8n Cloud lets a JavaScript Code node import, crypto and moment (Source: [n8n Docs: Code node](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.code), read 2026-11-04)
- **6.6k** GitHub stars on n8n-skills, a set of Claude Code skills with two for the Code node (Source: [Romuald Członkowski on GitHub: n8n-skills](https://github.com/czlonkowski/n8n-skills), read 2026-11-05)

| You want to | What the Code node does | Use instead |
| --- | --- | --- |
| Make an HTTP request | Not available | The HTTP Request node |
| Read or write a file | Not available | The Read/Write Files from Disk node |
| Use a credential | Not available by design, and `this.getCredentials()` fails | The HTTP Request node, which supports credentials |
| Import an npm module on self-hosted n8n | Blocked until you allow it | `NODE_FUNCTION_ALLOW_BUILTIN` and `NODE_FUNCTION_ALLOW_EXTERNAL`, set on the task runners when you use them |
| Import an npm module on n8n Cloud | Not possible | The two modules n8n provides, crypto and moment |

## What the maker of n8n-skills and Samir Saci say about Code node languages

Romuald Członkowski, who works at AiAdvisors in Warsaw, built [n8n-skills](https://github.com/czlonkowski/n8n-skills), a set of Claude Code skills for building n8n workflows. Its Python skill gives blunt advice: use JavaScript for 95% of use cases. The reasons it lists match the Python section above. Native Python sees only `_items` or `_item`, read as dicts, and the skill calls the import allowlist its critical limitation.

So write Code nodes in JavaScript by default, and keep Python for a self-hosted instance where the module you need is already allowed.

The n8n team [shared a post by Samir Saci on X](https://x.com/n8n_io/status/1973659279413403874) on 2 October 2025, about moving from Python to JavaScript in n8n. Saci, who describes himself as the founder of LogiGreen, used Code nodes for sales analytics and built ABC and Pareto charts. A port like his starts in Run Once for All Items, because a Pareto chart needs every row at once.

> Use JavaScript for 95% of use cases
>
> Romuald Członkowski, Creator of n8n-skills, AiAdvisors, [GitHub](https://github.com/czlonkowski/n8n-skills) (read 2026-11-05)

[![n8n.io (@n8n_io) on X, 2 October 2025. Great post by @Samir_Saci_ on moving from Python to JavaScript in n8n. He shows how to use Code nodes for sales analytics, build ABC and Pareto charts, and compare with FastAPI.](https://mindket.com/blog/shots/x-n8n-io-python-to-javascript.webp?v=7c6964f43e0a)](https://x.com/n8n_io/status/1973659279413403874)

n8n.io on X, 2 October 2025

> A screenshot of X's own embed of the post, taken on 5 November 2026, with the time in UTC. Select it to open the post on X.

## Common mistakes

- "Code doesn't return items properly" and "Code doesn't return an object". The node must return an array of objects that wrap their data in `json`. A script that ends without a `return`, or returns `undefined`, lands here, as the [common issues page](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.code/common-issues) explains.
- "A 'json' property isn't an object". You set `json` to an array. Put the array inside an object, such as `{ json: { rows } }`.
- "'import' and 'export' may only appear at the top level". The sandbox does not support them, so use `require()`, and on a self-hosted install allow the module first.
- "Cannot find module". Install the module into your n8n environment, and with Docker extend the official image. Then set `NODE_FUNCTION_ALLOW_BUILTIN` or `NODE_FUNCTION_ALLOW_EXTERNAL`. With external task runners, set them in the runners config file instead.
- Calling `$getCredentials()` or `this.getCredentials()`. It fails by design, so move the authenticated call to an HTTP Request node.
- Calling `$evaluateExpression()`. [n8n 3.0](https://docs.n8n.io/changelog/v30-breaking-changes) removed it from the JavaScript Code node, and secure-mode runners, the default since n8n 2.0, already fail on it. Evaluate the expression in a field of an earlier node and read the result.
- Running the node over huge data. The [memory page](https://docs.n8n.io/deploy/host-n8n/configure-n8n/scaling/fix-memory-issues) includes "Avoid using the Code node where possible" in its tips for cutting memory use.

## Try it yourself

- Run the all-items sample, then the each-item sample on the same input, and compare the output items.
- In the each-item sample, return `null` for items with no `name` and count how many items come out.
- Add `console.log($input.first())` and read the browser console while you run the node.
- If you self-host, allow one built-in module with `NODE_FUNCTION_ALLOW_BUILTIN=crypto`, load it with `require()` and hash a field.

## What to learn next

The Code node runs on task runners, and each worker in a scaled setup needs its own. [Lesson 4](https://mindket.com/learn/n8n-advanced/n8n-queue-mode) puts n8n into queue mode, with Redis, workers and the settings that decide how much runs at once. For the bigger picture of what n8n nodes can do before you reach for code, [what is n8n](https://mindket.com/blog/what-is-n8n) is the place to start.

## Check yourself

1. You use Run Once for Each Item. What should the code return?

   A. An array of items
   B. One item, such as { json: { ... } }
   C. A plain string

   Answer: B. Each-item mode runs the code once per input item and expects one item back, and null skips that item.

2. The Code node cannot reach credentials. Which node makes an authenticated API call?

   A. Edit Fields
   B. Read/Write Files from Disk
   C. Execute Sub-workflow
   D. HTTP Request

   Answer: D. The HTTP Request node supports credentials, which the Code node cannot access by design.

3. In native Python in the Code node, how do you read the name field of an input item?

   A. item["json"]["name"]
   B. item.json.name
   C. $json.name

   Answer: A. Native Python accepts only bracket access, and the dot form works in the retired Pyodide version.

4. In Run Once for All Items mode you create new items that later nodes must trace back. What do you set on each?

   A. binary
   B. itemMatching
   C. pairedItem

   Answer: C. New items are linked to no input unless you set pairedItem to the index of the input item.

## Frequently asked questions

### Can the n8n Code node make HTTP requests?

No. The docs say you can't access the file system or make HTTP requests in the Code node. Use the HTTP Request node, which also supports credentials, and the Read/Write Files from Disk node.

### Can I use npm packages in the Code node?

On self-hosted n8n, yes: NODE_FUNCTION_ALLOW_BUILTIN takes built-in module names, NODE_FUNCTION_ALLOW_EXTERNAL takes npm packages, and commas separate several names. With external task runners you set them on the runners. On n8n Cloud you cannot import external modules, and only crypto and moment are available.

### Can I import Python libraries in the Code node?

Not on n8n Cloud, where the Python option allows no imports at all. Self-hosters can add libraries to the n8nio/runners image and allowlist them, and the docs say the n8n team is committed to allowing arbitrary libraries securely in the long term.

### Do old Function nodes still run after upgrading?

No. A workflow that uses a removed node fails when it runs, and a published one does not activate when n8n starts, so its triggers stop firing. Before you upgrade, Settings, then Migration Report, lists the affected workflows.

### Why does my Code node complain about json?

Because json holds something other than an object, most often an array. Wrap the array in an object, such as { json: { rows } }. n8n adds a missing json key and the outer array for you, but it cannot fix a json that is itself an array.

### How do I debug code in the Code node?

Use console.log() in JavaScript or print() in Python, then open your browser's developer console and run the node. In native Python you can print `_items` or `_item` directly.

## Sources

- [n8n Docs: Code node](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.code) (read 2026-11-04)
- [n8n Docs: Using the Code node](https://docs.n8n.io/build/code-in-n8n/using-the-code-node) (read 2026-11-04)
- [n8n Docs: Code node common issues](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.code/common-issues) (read 2026-11-04)
- [n8n Docs: Enable modules in Code node](https://docs.n8n.io/deploy/host-n8n/configure-n8n/basic-configuration/configuration-examples/enable-modules-in-code-node) (read 2026-11-04)
- [n8n Docs: Understand n8n's data structure](https://docs.n8n.io/build/work-with-data/understand-n8ns-data-structure) (read 2026-11-04)
- [n8n Docs: Reference previous nodes](https://docs.n8n.io/build/work-with-data/reference-data/reference-previous-nodes) (read 2026-11-04)
- [n8n Docs: Use built-in shortcuts](https://docs.n8n.io/build/code-in-n8n/use-built-in-shortcuts) (read 2026-11-04)
- [n8n Docs: Output to the browser console](https://docs.n8n.io/build/code-in-n8n/cookbook/code-node/output-to-the-browser-console) (read 2026-11-04)
- [n8n Docs: Get the binary data buffer](https://docs.n8n.io/build/code-in-n8n/cookbook/code-node/get-the-binary-data-buffer) (read 2026-11-04)
- [n8n Docs: Accessing linked items in the Code node](https://docs.n8n.io/build/work-with-data/reference-data/link-data-items/accessing-linked-items-in-the-code-node) (read 2026-11-04)
- [n8n Docs: Preserving linking in the Code node](https://docs.n8n.io/build/work-with-data/reference-data/link-data-items/preserving-linking-in-the-code-node) (read 2026-11-04)
- [n8n Docs: Set up task runners](https://docs.n8n.io/deploy/host-n8n/configure-n8n/set-up-task-runners) (read 2026-11-04)
- [n8n Docs: Task runner environment variables](https://docs.n8n.io/deploy/host-n8n/configure-n8n/basic-configuration/use-environment-variables/task-runners) (read 2026-11-04)
- [n8n Docs: Fix memory issues](https://docs.n8n.io/deploy/host-n8n/configure-n8n/scaling/fix-memory-issues) (read 2026-11-04)
- [n8n Docs: v3.0 breaking changes](https://docs.n8n.io/changelog/v30-breaking-changes) (read 2026-11-05)
- [n8n repository: JavaScript task runner (js-task-runner.ts)](https://github.com/n8n-io/n8n/blob/master/packages/@n8n/task-runner/src/js-task-runner/js-task-runner.ts) (read 2026-11-04)
- [Romuald Członkowski on GitHub: n8n-skills](https://github.com/czlonkowski/n8n-skills) (read 2026-11-05)
- [n8n.io on X: great post by Samir Saci on moving from Python to JavaScript in n8n, 2 October 2025](https://x.com/n8n_io/status/1973659279413403874) (read 2026-11-05)

[Browse n8n workflows](https://mindket.com/automations/n8n)
