Workflow intermittently crashes and goes inactive on the same PDF file (n8n Cloud, Starter plan)

Describe the problem/error/question

My workflow processes PDF files (download → extract text via “Extract From File” node → further processing). It runs intermittently: the exact same PDF file sometimes completes successfully and sometimes fails, with no change to the workflow or the file itself.
When it fails, the workflow also ends up deactivated afterward, even though I never manually turned it off - it was published/active before the crash.
I’m on n8n Cloud, Starter plan (billed annually).

What is the error message (if any)?

No explicit error message is shown in the UI. The execution simply stops - “lastNodeExecuted” in the execution data shows the node right before “Extract From File” (our “Download file” node), and all nodes after that point show “isArtificialRecoveredEventItem”: true, meaning n8n reconstructed them rather than actually running them. Total execution time on these failed runs is very short (under ~5 seconds).

Please share your workflow


Share the output returned by the last node

There is no normal output - the execution stops mid-way. The last genuinely-executed node is “Download file”; everything after is an artificially recovered/empty item, not real output.

Information on your n8n setup

  • n8n version: Version 2.29.8
  • Database (default: SQLite): n8n Cloud managed (not self-hosted, so default SQLite doesn’t apply)
  • n8n EXECUTIONS_PROCESS setting (default: own, main): N/A - managed by n8n Cloud
  • Running n8n via (Docker, npm, n8n cloud, desktop app): n8n Cloud (Starter plan, billed annually)
  • Operating system: N/A - cloud-hosted

Hi @zyll

Based on the symptoms you’ve described, this is not a standard “node error” but a process-level crash (likely an Out-of-Memory / OOM event).

If you are processing multiple files in a loop, do not process them all in one “batch.”

  • Use a Split In Batches node to process PDFs one by one.
  • Ensure there is a small delay (Wait node) between files to allow the system to garbage-collect memory.

Since you are on n8n Cloud, you cannot change the NODE_OPTIONS=--max-old-space-size manually. However, you can:

  • Check for concurrent executions​: Go to your settings and ensure you aren’t running too many workflows simultaneously.
  • Optimize the PDF​: If the PDFs are exceptionally large or contain high-resolution images, they consume more RAM during extraction even if you only want the text.

If the “Extract From File” node continues to crash, the internal library it uses might be too heavy for the Starter plan’s RAM. Consider using an external API for PDF extraction:

  • OCR.space or Adobe PDF Services API​: These move the memory burden from your n8n instance to an external server.
  • Convert to Text first​: If possible, have the source system provide a .txt or .json file instead of a .pdf.

Because your workflow is being automatically deactivated​, this is an infrastructure-level event. I strongly recommend opening a support ticket with n8n Cloud. Provide them with:

  • The Execution ID of a failed run.
  • The mention of isArtificialRecoveredEventItem: true.
  • The fact that the workflow is being deactivated automatically.

They can check the backend logs (which you cannot see on Cloud) to confirm if it was a SIGKILL (OOM) or a specific segmentation fault in the PDF parsing library.

Hi @zyll Welcome!
The auto-deactivation is expected n8n Cloud behavior, not a config problem: a process-level crash (OOM/SIGKILL, or a native crash in the PDF parser) trips an intentional safety deactivation, and because it’s a hard crash rather than a node error it also bypasses your Error Workflow, which is why nothing is saved and no alert fires. There’s no workflow-level setting to turn this off on Cloud. Since a crash won’t trigger an Error Workflow and audit-log streaming is Enterprise-only, the Starter-viable way to stop getting blindsided is to poll the workflow’s active state from an outside scheduler and re-activate it through the n8n API, which also keeps it off your execution quota.
See this:

kjooleng’s OOM read is right, but your own detail (intermittent, on the same file) actually narrows it a lot, because a file that is simply too big fails every time, not sometimes. Identical input failing only occasionally is the signature of concurrency-coupled memory: that PDF’s extraction pushes the instance over the Starter plan RAM ceiling only when it happens to run alongside other executions. On a quiet minute it fits, on a busy minute the same file OOMs. That is why it looks random, and it is why “optimize the PDF” will not fully fix it. The variable is not the file, it is what else is running at the same moment.

Two things follow. First, cap this workflow’s concurrency so it cannot overlap heavy runs. On Cloud the practical lever is making sure the PDF path cannot be triggered several times in parallel (a gate or a queue in front of it), so peak memory is one file’s worth rather than three. Second, and this is a bigger memory lever than Split In Batches when there is only one file: drop the binary as early as you can. “Extract From File” loads the whole PDF into the item as binary, and if that binary field is carried through the downstream nodes, copies are retained at each step and your peak multiplies. Extract the text, then immediately Set or select only the text field so the binary is not dragged along. That alone often keeps a borderline file under the ceiling.

On the auto-unpublish being intentional safety behaviour, that is true, but it is worth separating the behaviour from the consequence: knowing that n8n deactivates after repeated crashes does not help you find out that it happened. Once the workflow is inactive no executions are created, so the Error Trigger never fires, because there is nothing to attach an error to, and you learn about it from missing output rather than from an alert. So even after the memory fix, add an external heartbeat: have the workflow ping a health monitor (Healthchecks.io, or just a timestamped row somewhere) on each successful run, and alert when the expected run does not arrive. That turns “silently deactivated since Tuesday” into “alerted in minutes,” which on a document pipeline is the failure that actually costs you.

Log the file size, page count and node memory use on both successful and failed runs. If the same PDF only fails intermittently the execution data may show a resource limit or timeout rather than bad content.

On top of capping concurrency, try moving Extract From File into a sub-workflow called with Execute Workflow. The parent then holds only the small JSON result, and the binary is released when the sub-execution ends instead of riding along in every downstream node’s input — that input-carrying is where the memory actually multiplies.

And since Cloud deactivates on a hard crash and skips your error workflow, add a scheduled watchdog that reads active on the public API and re-activates plus alerts. Otherwise the first thing you learn is that it’s been off for three days.

@colemaffeo6 named the right shape for the second symptom — a scheduled watchdog that reads active on the public API. I built that a few days ago for my own instances, so here it is as a working thing rather than a description of one.

Why that half is worth tooling at all: a hard crash kills the process before the Error Workflow can fire, so the one mechanism that’s supposed to tell you is the one that can’t. And the auto-deactivation is correct behaviour — it stops a crash loop — it’s just silent, and silence is indistinguishable from working.

How it works:

  1. snapshot records which workflows are currently active — that becomes the expected set.
  2. check fetches live state and exits 1 if any of them is no longer active.
  3. Cron runs check, and the exit code drives whatever alerting you already have — Healthchecks.io, a curl to your own webhook, anything that reads a status.

One thing I changed my mind about while building it: I left the re-activation out. Flipping the workflow back on after a memory kill runs the same file into the same ceiling, so on a bad day you get a flapping workflow and a quieter version of the same outage. It counts drops instead, and once one has dropped a few times it says so, because at that point the answer is the concurrency profile, not the on switch. If your crashes are rare and unrelated to load, re-activating is the better trade and it’s a short function to add.

Where it breaks: your polling interval is your blind window, so checking every five minutes means up to five minutes of collecting nothing before anyone knows. And it can’t tell a crash from you deliberately switching something off — re-run snapshot after any intentional change, or it will page you about your own edit.

Stdlib only. Needs an API key from Settings > n8n API; the public API isn’t available on the free trial, so a 401 there is usually the plan rather than the key.

Not a fix for the crash itself, but might help you see what else is exposed —
drop your exported workflow JSON into this scanner and it flags nodes
with continueRegularOutput, missing error branches, no retry/timeout,
unauthenticated webhooks, hardcoded credentials.

Given that lastNodeExecuted stops before the crash point, worth checking
whether that node’s error handling is swallowing the failure silently.

Browser-local, no login, no upload.

thank you for the help everyone, it’s working now