My workflow works perfectly, but when I attach memory to the LLM (OpenAI), which is almost at the middle of the workflow. many code nodes which are before http node (for sending payload to dashboard)
I am running into a severe performance issue where my Code nodes freeze and eventually time out, but only when LLM memory is present in the workflow.
My workflow processes incoming JSON data using a few standard Code nodes (performing data cleaning and validation). Further down the workflow, I have an LLM node (OpenAI) with a memory component attached.
When I run the workflow without the LLM memory, everything executes perfectly and instantly. However, the moment I attach memory to the LLM, several code nodes that execute before an HTTP request node get stuck in an infinite hang.
What is the error message (if any)?
Something like this: there is no error message anymore, just infinite execution. Error:
Task execution timed out after 300 seconds
The task runner was taking too long on this task, so it was suspected of being unresponsive and restarted, and the task was aborted. You can try the following: 1. Optimize your script to prevent long-running tasks, e.g. by processing data in smaller batches. 2. Ensure that all paths in your script are able to terminate, i.e. no infinite loops. 3. If your task can reasonably take more than 300 seconds, increase the timeout using the N8N_RUNNERS_TASK_TIMEOUT environment variable.
is a specific n8n safeguard. It means that the JavaScript code inside your Code nodes is running for more than 300 seconds, causing the n8n Task Runner to assume it is stuck in an infinite loop or processing an impossibly large task, so it forcefully kills it.
Since this only happens when you attach Memory to the LLM, the Memory component is fundamentally changing the data structure, size, or behavior of the data flowing into your downstream Code nodes.
When Memory is attached, the LLM node (or the chain/agent it is part of) may be passing the entire conversation history or a large memory state object into the main data stream, rather than just the final AI response.
The Issue: If your Code nodes are trying to process, clean, or JSON.stringify() an input that now contains hundreds or thousands of historical messages, it will easily exceed the 300-second CPU timeout.
The Fix: You need to strip the data down to only what the dashboard needs immediately after the LLM node.
Add a temporary Code node right after the LLM node with this code to see what is actually being passed:
// Check how many items and the size of the data
const items = $input.all();
console.log("Total items:", items.length);
console.log("First item keys:", Object.keys(items[0].json));
return items;
If you see a massive messages array or memory object, update your downstream Code nodes to only extract the specific field you need (e.g., item.json.message.content or item.json.text) and discard the rest before processing.
Memory objects in n8n (especially when dealing with LangChain integrations) can sometimes contain circular references (where an object references itself).
The Issue: If your Code nodes use JSON.stringify($input.all()) or pass the entire input object into a custom parsing function, a circular reference can cause the JavaScript engine to enter an infinite loop trying to serialize the object, resulting in the 300s timeout.
The Fix: Never stringify the entire $input or $input.all() if it contains LLM/Memory outputs. Always extract the primitive string values first:
// BAD: Can hang if circular references exist
// const payload = JSON.stringify($input.all());
// GOOD: Extract only the primitive data you need
const cleanData = $input.all().map(item => ({
response: item.json.message?.content || item.json.text,
// add other specific fields here
}));
const payload = JSON.stringify(cleanData);
If your Code nodes use while loops, recursive functions, or .reduce() methods that depend on the structure of the incoming JSON, the addition of Memory might have changed that structure.
The Issue: For example, if your code has a while loop that processes an array until it is empty, but the Memory component accidentally injects a nested array that keeps regenerating or doesn’t meet the exit condition, the loop will run forever.
The Fix: Review all while loops in your Code nodes. Add a “safety counter” to force them to break if they exceed a reasonable number of iterations:
let safetyCounter = 0;
while (myCondition && safetyCounter < 1000) {
// your logic
safetyCounter++;
}
As I said, the memory attached with LLM is in the middle of the workflow.
And once I attached the memory, I faced problems with several code nodes, and some code nodes are at the start of the workflow (before the llm memory node even executes).
Without memory, the workflow completes execution with no issue, but with memory, the same workflow start having issue at code node
Hi @sherazbintahir
Code nodes hanging purely from the presence of a sub-node, including ones that run before it, is the task runner failing to resolve that sub-node’s type. Anything that makes a Code node ask the main process for extra context, a $('Node Name') or $node["Node Name"] reference or a require() of an external module, sends the runner back to rebuild the workflow, and a sub-node type it can’t resolve leaves that request unanswered until the 300s kill. Your n8n container logs will show “Unrecognized node type: …” at the moment it stalls.
Rewrite those Code nodes to use only $input and $json, and move anything they need from an earlier node onto the main path with a Set node first. Turning the runner off isn’t an option on 2.11.3, N8N_RUNNERS_ENABLED is deprecated from 2.0 and every Code node execution runs on a runner.
Thanks, it will help a lot. But I’m confused here because my complete workflow (120+ nodes) works perfectly without any error, but when I attach the memory with LLM (AI agent node with OpenAI + memory) i face this problem.
For more info, in the workflow without memory, I use the OpenAI node directly. And i am not facing this issue on all code node but few.
Yellow Box: Where I am attaching memory with LLM.
Red Dots: Where I am facing code node problems. Mostly nodes are those in which i am building/preparing payload to send on the dashboard.
Hi @sherazbintahir This isn’t slowness , your Code nodes are deadlocked, not busy.
Since v2.0 all Code nodes run in a separate task runner process. If a script only uses `input‘/‘input` / ` input‘/‘json`, it gets a slim payload and runs instantly. But if it uses `(′NodeName′)‘or‘(‘Node Name’)` or ` (′NodeName′)‘or‘node[‘Node Name’]`, the runner has to request the whole serialized workflow back from n8n and rebuild it and that requires resolving every node type on the canvas, sub-nodes included. Attach the memory subnode and the runner hits a type it can’t resolve, the request never returns, and your Code node waits forever until the 300s watchdog kills it. Same as #20752.
That also explains why only some of your Code nodes break — the working ones are the ones that never reach outside their own input.
Open one of the frozen Code nodes — does it contain $('...') or $node[...] anywhere?
If it’s yes to both, the fix is quick: put a Set node in front of it and pass the value in as an expression (={{ $('Clean JSON').first().json.config }} — expressions in normal nodes run in the main process and are unaffected), then read it from $input inside the Code node. Memory stays exactly where it is.
Post that what the log line says and I’ll give you the exact rewrite for your node.
@sherazbintahir The variable isn’t memory — it’s the node swap. Without memory you used the plain OpenAI node. To attach memory you had to switch to the AI Agent, a LangChain cluster root that pulls sub-nodes onto the canvas (Chat Model, Memory, your search_workwell_memory tool). The OpenAI node resolves fine in the task runner; Agent sub-nodes often don’t.
Why only some Code nodes: since v2.0 all Code nodes run in a separate runner process.
Uses $('Node') / $node['Node'] / $items() -runner requests the entire serialized workflow back and rebuilds it, which means resolving every node type on your 120-node canvas, sub-nodes included. One unresolvable type - request never returns - hang until the 300s watchdog fires. not (your payload builders — the red dots)
Note the tool sub-node can cause this alone too: #20752 was postgrestool, #20132 Apify/Perplexity — there it hung even though the Agent never executed.
Confirm in 30s — leave memory attached, stub one frozen node:
Merge node into the Code node, then read $input.all(). Cleanest at your scale.
Set node in front, resolve values as expressions: ={{ $('Parse Extraction').first().json.score }} expressions in normal nodes evaluate in the main process, so they’re immune.
Skip the Code node — build the JSON body directly in the HTTP Request node with expressions.
Keep pairedItem: { item: index } on returned items, or downstream expressions reintroduce the problem. Memory stays attached in all three.
Won’t help: raising N8N_RUNNERS_TASK_TIMEOUT (the wait is unbounded), or N8N_RUNNERS_ENABLED=false (ignored in 2.x).
Can you post the output of docker logs -f <n8n-container> | grep -i "unrecognized" while running with the Agent connected? That’ll show whether it’s the memory or the tool.