Hi n8n Team,I am writing to share feedback and request a quality-of-life feature improvement regarding how the Code Node (JavaScript) handles dynamic text outputs generated by AI Agents (Advanced AI nodes).
My Environmentn8n Version: 2.26.8 (Self-Hosted)Deployment: Running locally on Docker DesktopAccess Method: Exposed via an ngrok tunnelAI Model: Gemma 4 e4b / ChatGPT-4o-mini inside the AI Agent node.
The Issue / Friction PointI am trying to build an automated workflow where an AI Agent generates a dynamic JavaScript code snippet based on a user prompt to process Google Sheets data. The output text of the AI Agent is then passed into a subsequent Code Node using the native expression syntax: {{ $json.output }}.However, because the AI Agent outputs data as a literal text string, the Code Node treats the injected expression as a static String object rather than parsing and compiling it as executable source code. This continuously triggers the standard validation block error:json{
“errorMessage”: “Code doesn’t return items properly”,
“errorDescription”: “Please return an array of objects, one for each item you would like to output.”
}
Use code with caution.Even when instructing the LLM to output raw JSON arrays ([…]) or using Immediate Invoked Function Expressions (IIFE), the containerized Docker sandbox environment via the ngrok tunnel rigidly enforces data payload transmission as string literals, making it impossible to bypass this restriction purely by prompt engineering.The only workaround is manually altering the Code Node syntax to force a local execution wrapper like new Function($input.first().json.output)(), which defeats the purpose of an autonomous, zero-touch AI Agent generating dynamic workflows.
Proposed Solutions / Feature EnhancementsTo bridge the gap between Advanced AI generation and the native Code Node runtime, it would be incredible if the development team could implement one of the following upgrades:A “Dynamic Execution” Toggle in the Code Node: Add a simple UI toggle switch (e.g., “Allow Expression Compilation” or “Execute Input String as Code”). When enabled, if the code box detects an expression syntax like {{ $json.output }}, it will automatically compile the internal string string text into the V8 engine using a secure sandbox runner, instead of throwing a static validation failure.Implicit Auto-Parsing for Stringified JSON Arrays: Update the underlying validateRunCodeAllItems check. If the stringified output returned strictly begins with [ and ends with ], n8n could implicitly run a soft JSON.parse() wrapper on behalf of the user to convert the data stream into a legitimate n8n Array of Objects.Native “n8n Data Array” Structured Output Mode for AI Agents: Enhance the AI Agent/Advanced AI nodes so users can enforce an output schema natively conforming to the n8n data structure, forcing the AI node itself to cast the string block into an actual array array before hitting subsequent nodes.This upgrade would dramatically empower developers building AI-driven autonomous workflows within containerized or tunneled local environments.Thank you for your continuous amazing work on n8n!
Interesting request — but you can unblock your actual use case today without n8n eval-ing AI-generated code (which you probably don’t want in production anyway: running LLM-generated JS through new Function() is arbitrary code execution, and one prompt injection turns your sandbox into someone else’s).
The key realization: you don’t need the Code Node to compile AI-generated code — you need the AI to return a data array, and the Code Node to hand that back as items. Two cleaner paths:
-
Make the AI return JSON, then parse it (works right now). Have the Agent output a JSON array, then in the Code Node:
return JSON.parse($input.first().json.output).map(o => ({ json: o }));
That “Code doesn’t return items properly” error is just n8n telling you the node didn’t return [{json:{…}}, …] — it’s about the return shape, not about compiling. Parse the string, map it to items, and it passes. -
Use the Structured Output Parser on the AI Agent — this is basically the native feature you’re asking for in proposal #3. Attach it to the Agent and define the schema (array of objects). The Agent then returns schema-conforming structured data instead of a loose text string, so the next node receives a real array — no JSON.parse, no new Function, no string-vs-code mismatch. That’s your zero-touch path.
So the part I’d drop is the “generate code → execute code” pattern. AI → structured data → deterministic Code Node is more reliable, more secure, and already fully supported. Let the AI generate the data, not the code that produces it.
One more thing: your Docker/ngrok setup isn’t the blocker. The same string-vs-items behavior happens on any n8n install — it’s the Code Node’s return contract, not the sandbox.
If you paste your Agent node + Code Node, I’ll show you the exact two-line fix.