czlonkowski/n8n-skills/n8n-code-javascript
- community
Checking that the SKILL.md file is still in the repository.
Write, review, or debug JavaScript in an n8n Code node. Use when a Code node is already in the workflow (editing it, fixing an error, choosing its mode, making it faster), or when a new one is justified: no native node fits (check the job-to-node table in using-n8n-mcp-skills first) and the job is on the closed list — loops or recursion no node expresses, state across runs, parsing no node handles, an allowlisted library, heavy all-items work, or one short node replacing 4+ glue nodes. Covers $input/$json/$node in code, this.helpers, Luxon, SplitInBatches loops, cross-iteration data, pairedItem, per-item performance, and the \"Why Code:\" note. Filtering, totals, dedupe, sorting, joins, file formats and API paging have native nodes (Filter, Summarize, Remove Duplicates, Sort, Merge, Extract From File, HTTP Request): see n8n-node-configuration. EXCEPTION — for the AI-agent-callable Custom Code Tool (@n8n/n8n-nodes-langchain.toolCode), use n8n-code-tool; it has a different runtime contract.
Install
npx vskill@latest install czlonkowski/n8n-skills/n8n-code-javascriptSKILL.md
JavaScript Code Node
Expert guidance for writing JavaScript code in n8n Code nodes.
Before you write a Code node
A new Code node has to pass this gate first:
- Is there a native node for the job? Check the job-to-node table in
using-n8n-mcp-skills: Filter, IF / Switch,
Summarize, Aggregate, Split Out, Merge, Compare Datasets, Remove Duplicates, Sort + Limit, Date & Time, XML / HTML / Extract From File / Convert To File, HTTP Request (pagination, batching) and Crypto cover most reaches for Code. Their configs are in n8n-node-configuration → NATIVE_NODES.md.
- Would a short expression in that node do? One expression, no function body — the helper methods (
.pluck(),
.sum(), .unique(), $ifEmpty(), .diffTo()) are in n8n-expression-syntax and, on n8n-mcp 2.97.0+, in tools_documentation({topic: "expression_helpers"}). Several statements inside {{ }} count as code, so they belong here rather than in an Edit Fields field.
- Is the job on the closed list? Loops or recursion no node expresses, state across runs
($getWorkflowStaticData), parsing no node handles, an allowlisted library, heavy all-items work (thousands of items, stated or measured), or one short Code node (~15 lines) replacing 4+ glue nodes that only reshape data.
If it passes, write the Code node and give it a note, so the next reader (and the review hooks) can see why:
Editing or debugging a Code node that is already there doesn't need the gate, but if the node does a native-node job, say so and offer the native replacement.
Quick Start
Essential Rules
- Choose "Run Once for All Items" mode (recommended for most use cases)
- Access data:
$input.all(),$input.first(), or$input.item - Return `[{json: {...}}]` — the canonical, mode-portable form. In Run Once for All Items mode n8n also auto-wraps a bare
return {…}object, so that runs too; what genuinely fails is returning a primitive (string/number) ornull. - CRITICAL: Webhook data is under
$json.body(not$jsondirectly) - Built-ins available:
this.helpers.httpRequest()(no auth — the bare$helpersglobal is undefined in the task-runner sandbox, so$helpers.httpRequest()throwsReferenceError: $helpers is not defined), DateTime (Luxon), $jmespath(). Not available:this.helpers.httpRequestWithAuthentication(deny-listed), $env (when N8N_BLOCK_ENV_ACCESS_IN_NODE=true), require() (unless allowlisted). For anything beyond a trivial unauthenticated GET (auth, pagination, retries), prefer the HTTP Request node and keep Code nodes for pure logic. - Instance-allowlisted libraries: Self-hosted instances can allowlist modules via
N8N_RUNNERS_ALLOWED_BUILT_IN_MODULESandN8N_RUNNERS_ALLOWED_EXTERNAL_MODULES(legacy:NODE_FUNCTION_ALLOW_BUILTIN/NODE_FUNCTION_ALLOW_EXTERNAL). If the user says their instance allows specific modules (e.g.axios,lodash,crypto), use them viarequire()— don't refuse. If unsure, ask or default to built-ins only. - Wrong skill? If you're writing code for a Custom Code Tool attached to an AI Agent (
@n8n/n8n-nodes-langchain.toolCode), stop — that node has a different contract (input viaquery, must return a string, no$input/$helpers). Use the n8n-code-tool skill.
Mode Selection Guide
The Code node offers two execution modes. Choose based on your use case:
Run Once for All Items (Recommended - Default)
Use this mode for: 95% of use cases
- How it works: Code executes once regardless of input count
- Data access:
$input.all()oritemsarray - Best for: logic that needs every item at once and passed the gate above
- Performance: Faster for multiple items (single execution)
When to use:
- ✅ Each item depends on earlier items (running totals, sessionizing events, gap detection)
- ✅ Multi-pass algorithms or recursion over nested data of unknown depth
- ✅ Heavy transforms over thousands of items where one node beats a long chain (measured)
Native first: totals, averages and counts → Summarize; sorting or ranking → Sort + Limit; deduplication → Remove Duplicates; items into one array → Aggregate; joining two lists → Merge.
Run Once for Each Item
Use this mode for: Specialized cases only
- How it works: Code executes separately for each input item
- Data access:
$input.itemor$item - Best for: Item-specific logic, independent operations, per-item validation
- Performance: Slower for large datasets (multiple executions)
When to use:
- ✅ Each item needs independent API call
- ✅ Per-item validation with different error handling
- ✅ Item-specific transformations based on item properties
- ✅ When items must be processed separately for business logic
Decision Shortcut:
- Need to look at multiple items? → Use "All Items" mode
- Each item completely independent? → Use "Each Item" mode
- Not sure? → Use "All Items" mode (you can always loop inside)
Why "All Items" is faster — the per-item boundary
Mode choice is the single biggest performance lever in a Code node. Each per-item execution context costs a setup tax (measured on n8n 2.x, small records):
| What runs per item | Approx. cost | |
|---|---|---|
| Code All Items (one run for the whole set) | ~0.02 ms/item | |
| Expression in any node (IF / Set / etc.) | ~0.2 ms/item | |
| Code Each Item (a full sandbox per item) | ~0.6 ms/item — ~25–30× All Items |
So Run Once for Each Item over 10k items is ~6 s of pure overhead vs ~0.2 s in Run Once for All Items. Use Each Item only when an item genuinely needs isolating (independent error handling, or a per-item API call you can't batch); otherwise loop inside one All Items node. Expression complexity itself is essentially free (~90% of the cost is the per-item context, not your code) and every node→node hop re-copies all items — so reduce the number of per-item boundaries, don't micro-optimize each one.
On top of the per-item cost, every Code node run pays a fixed hand-off to the task runner. In the default internal mode the runner stops after 15 s idle (N8N_RUNNERS_AUTO_SHUTDOWN_TIMEOUT), so a workflow that runs now and then pays a cold start of hundreds of milliseconds on most runs. Native transform nodes process all items in one in-process call and skip that hand-off.
What this means for node choice. Most workflows are I/O-bound, and below a few hundred items none of these costs matter: choose by readability, which means native nodes first. Performance becomes the deciding argument only for heavy all-items work — thousands of items per run, transform work rather than I/O dominating, stated by the user or measured. Then one All Items Code node can beat a long chain of nodes, and the reason goes in its Why Code: note. These figures are the pack's one measured reference; the other skills point here instead of repeating them.
See: DATA_ACCESS.md → "Mode Performance" for the corollaries, hop costs, and scale check.
Data Access Patterns
Four ways to pull data from upstream nodes. Note $node["Name"] and $('Name') need .first().json or .all() — never .json directly.
Always access fields via .json (e.g. item.json.name, not item.name), and prefer the explicit $input.first().json.field over a bare $json.field.
See: DATA_ACCESS.md for the full guide — every pattern with examples, a decision tree, and the common mistakes (mutating originals, missing length checks, $input.item in the wrong mode).
Critical: Webhook Data Structure
MOST COMMON MISTAKE: Webhook data is nested under .body
Why: Webhook node wraps all request data under body property. This includes POST data, query parameters, and JSON payloads.
See: DATA_ACCESS.md for full webhook structure details
Return Format Requirements
Canonical form: [{json: {...}}] — an array of objects each with a json property. It is unambiguous and works identically in both execution modes, so make it your default.
In Run Once for All Items mode n8n auto-normalizes looser shapes on the way out: a single bare object, or an array of bare objects, gets wrapped under json for you. So return {foo: 1} runs. What has nothing to wrap — and therefore genuinely fails at runtime with "Code doesn't return items properly" — is a primitive (string/number/boolean) or null/undefined. (n8n-mcp ≥ 2.63.0 no longer flags a bare-object return as an error; it reflects this auto-wrap behavior.)
Correct Return Formats
Non-Canonical Returns (auto-wrapped — prefer the canonical form)
Genuinely Broken Returns
Why it matters: The canonical [{json: {...}}] is unambiguous and behaves the same in both modes. n8n auto-normalizes bare objects and arrays-of-objects in All Items mode, but a primitive or null return has nothing to wrap and stops execution.
See: ERROR_PATTERNS.md #3 for detailed error solutions
Common Patterns Overview
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassed, 100 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationPassed, 82 of 100Effective. 1 run. Evaluated 7 months ago.
Source
- SKILL.md in the repositoryCheckingskills/n8n-code-javascript/SKILL.md
Popularity
- Repository stars
- 3,875
- Repository forks
- 680
- 7-day trend score
- 41
Stars and forks are for the whole GitHub repository, not this skill alone. Refreshed 28 Mar 2026, 7 months ago.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/czlonkowski/n8n-skills/n8n-code-javascript)