We are intermittently encountering the following error in n8n:
Problem executing workflow
There was a problem executing the workflow.
Regular expression execution timed out
The issue does not appear to be limited to one particular workflow or node. It occasionally occurs across multiple unrelated workflows.
What we have observed:
The error occurs intermittently rather than on every execution.
It is not limited to a specific workflow or node.
Retrying the same workflow sometimes completes successfully.
It appears to occur even in workflows that do not explicitly use regular expressions.
We have not yet determined whether it is related to concurrent workflow executions.
n8n version: 2.36.7
Questions:
Is this a known issue in n8n or one of its internal dependencies?
Can this error occur even when a workflow does not explicitly use regular expressions?
Which logging level or environment variables should we enable to identify the source?
Is there a way to identify which expression or node triggered the regular expression timeout?
Could high concurrency, CPU usage, or memory pressure cause this error intermittently?
Please let us know which logs, stack traces, or diagnostic information would be most helpful. Any guidance from users who have experienced a similar issue would be greatly appreciated.
plzcheck whether you have N8N_EXPRESSION_ENGINE set to vm. That’s the only path where an expression gets interrupted at all, since the default legacy engine runs them without isolation and without any timeout, and vm is still marked experimental in the docs.
What makes it look random is N8N_EXPRESSION_ENGINE_POOL_SIZE, which defaults to 1. Every expression on the whole instance queues for that one warm V8 isolate against a 5000ms wall clock, so under concurrency a trivial expression in any workflow can blow the budget. That’s your intermittent, your unrelated workflows, and your passing retries. Raise the pool size and N8N_EXPRESSION_ENGINE_TIMEOUT, or set the engine back to legacy to rule it out in one restart.
Hi @a2sembly Welcome!
That string comes from the ReDoS guard n8n-workflow added in 2.35, which runs every regex inside a node:vm script with a 250ms timeout. The budget is wall clock rather than CPU time, so the process only has to lose the CPU briefly, from concurrent executions, a container CPU quota, or a GC pause, for a cheap pattern to overrun it and for a retry to pass.
It fires in workflows with no regex of your own because the same guard backs node parameter display conditions, parameter validation, IF and Filter conditions, and expression resolution. It sits outside the expression engine, so it applies on the default legacy setting, and the 250ms is hardcoded with no env var to raise it, still hardcoded in the 2.37 beta.
The lever is CPU headroom. If you are self-hosted, cap concurrent executions so they stop contending, then raise the cap from there:
The cause and the concurrency fix above are spot on, so I will just add the part questions 3 and 4 were really after: how to find the culprit, and how to stop an intermittent trip from quietly costing you a run.
To pinpoint it, set N8N_LOG_LEVEL=debug so the failing node and execution id show up in the logs, and point every critical workflow at one central Error Trigger workflow that records the execution id, the workflow name and the last node into a sheet or table. Because this fires intermittently across many unrelated workflows, a few days of that log turns “random everywhere” into a ranked list of which workflows and nodes actually trip it, which is usually a handful of heavy IF, Filter or Set expressions running over large item sets.
On not losing work: the timeout throws, so it is at least a loud error rather than a silent wrong output, which is good. But an intermittent hard error still drops that run unless you catch it. Since you noticed a retry usually passes, have the Error Trigger path retry the execution once and only alert you if the retry also fails. That way the flaky ones self heal and you only get pinged when something is genuinely stuck, instead of a run quietly vanishing. And if the workflow writes rows downstream, a simple daily count against an expected floor tells you on the rare occasion a trip actually cost you data rather than just a retry.