n8n execution crashed, startedAt null? It's a queue mode race

Your executions list shows crashed. The execution has no start time, no node ever ran, and the workflow logs are empty. If you took n8n 2.45.0 when it shipped on October 20, 2026, that isn't your workflow failing. It's a race in queue mode that n8n patched the next day.
Quick answer: An n8n execution markedcrashedwithstartedAt = nullin queue mode is a bug in n8n 2.45.0, fixed in 2.45.1 (released October 21, 2026). An idle worker claimed a Redis queue job and its lock in two separate steps, so a worker whose event loop was blocked could hold an active job with no lock. n8n's stall sweep then failed that job immediately, because n8n setsmaxStalledCountto 0 and no longer retries stalled jobs. Pin your Docker image ton8nio/n8n:2.45.1or later and recreate the container. If a video step is what blocks your event loop (FFmpeg in Execute Command, a Code node on a video buffer), move it to an HTTP submit-and-poll call against a media API like FFmpeg Micro so no long synchronous work runs inside n8n at all.
Why the execution says crashed but has no start time
The conventional read is that crashed means the process died mid-run: OOM kill, container restart, worker eviction. That's usually right, and it's why most troubleshooting guides send you to docker logs and memory limits. But startedAt = null rules all of that out. The execution never began.
The mechanism is in n8n PR #41525. An idle Bull worker waits for work with a blocking Redis BRPOPLPUSH from wait to active. Redis moves the job to active the instant it's available, and the worker sets the job's lock in a later call. Between those two operations, the job is active and unlocked. If the worker's event loop is busy in that window, the lock never gets set, the stall check sweeps, finds an active job with no lock, and fails it. Because n8n sets maxStalledCount to 0, there's no retry. The row lands as crashed with a null startedAt.
The fix inverts the order: the idle worker waits for a job without taking it, then takes the job and its lock in one Redis script. A worker with a blocked event loop holds nothing, and another worker picks the job up.
How to tell this apart from an OOM kill or a dead worker
Three signals separate the 2.45.0 race from an actual worker death.
startedAtisnulland no node has any run data. A worker that died mid-execution leaves a start time and partial node output.- The worker container is still up, with no restart and no
OOMKilledindocker inspect. The process survived; only the job was lost. - It's intermittent and tracks your long-running workflows, not memory pressure. The race needs a busy event loop, so it hits when something else is chewing on a file.
An OOM-killed worker shows the opposite shape: a start time, some completed nodes, and exit code 137 on the container.
Which version to run, and how to make the upgrade apply
2.45.0 shipped on October 20, 2026 and carries the race. n8n 2.45.1 landed the next day with the core fix "Claim an idle worker's next queue job and its lock in one step (#41558)". PR #41558 is the backport of #41525 onto the 2.45.x release branch. 2.45.2 and 2.45.3 followed on October 22 and 23. 2.45.1 is the floor, with no reason to stop there.
Pin the tag explicitly rather than trusting latest:
services:
n8n:
image: n8nio/n8n:2.45.3
n8n-worker:
image: n8nio/n8n:2.45.3
command: worker
Then recreate, not just pull:
docker compose pull
docker compose up -d --force-recreate n8n n8n-worker
docker compose exec n8n n8n --version
A pull that doesn't recreate the container leaves you running the old image, the most common reason an n8n patch appears not to have worked. We covered that trap in docker compose pull won't apply the n8n security update patch.
To prove the fix landed, run one execution that occupies a worker for several minutes, then submit a second while the first is mid-flight. On 2.45.0 the second comes back crashed with no start time. On 2.45.1+ it queues and runs. Lost executions don't re-run themselves, so replay them from the executions list by hand.
No env var fixes this
QUEUE_WORKER_MAX_STALLED_COUNT is the knob community threads keep pointing at, and it does nothing. n8n removed it in 2.0 and no longer auto-retries stalled jobs. One widely-read thread, queue mode reliability much worse after upgrading to v2.x, has self-hosters reporting failure rates climbing from roughly 1-2% on 1.x to 5-20% on 2.x and blaming that removal. The missing retry is real, but it's the reason the race is fatal, not the reason it happens.
The lease settings in n8n's queue mode environment variables explain why a blocking node is dangerous here:
| Setting | Default | What it means |
|---|---|---|
| `QUEUE_WORKER_LOCK_DURATION` | 60000 ms | A job's lock expires after 60 seconds |
| `QUEUE_WORKER_LOCK_RENEW_TIME` | 10000 ms | The worker must renew every 10 seconds |
| `QUEUE_WORKER_STALLED_INTERVAL` | 30000 ms | The stall sweep runs every 30 seconds |
Renewing a lease every 10 seconds requires the event loop to be free every 10 seconds. A node that pegs it for four minutes misses 24 renewals. Raising QUEUE_WORKER_LOCK_DURATION to 600000 buys ten minutes of headroom and moves the failure instead of removing it: the next job that blocks for eleven minutes fails the same way, and genuine worker deaths now take ten minutes to detect.
What in your workflow blocks the event loop for minutes
The race needs a worker that can't answer Redis for a while, and in content-automation pipelines that's almost always the video step. Node.js runs your workflow on one thread, so anything synchronous and long starves everything else on that worker, including lock renewal. The usual suspects:
- FFmpeg through the Execute Command node. n8n disabled this node by default in 2.0, and a 1080p transcode holds the worker for minutes.
- A Code node operating on a video buffer. Base64-encoding or slicing a few hundred megabytes in JavaScript is synchronous CPU work on the main thread.
- Read/Write Files from Disk on a large MP4. A 1 GB read is the classic n8n memory-and-blocking failure, and it's distinct from a timeout.
Upgrading to 2.45.1 stops the lost-job symptom. It doesn't make those steps safe. A worker pinned at 100% CPU for four minutes still isn't processing anything else, and its memory ceiling is still your largest input file. The durable fix is that the bytes never enter the n8n process.
Make the video step an HTTP submit, poll, download
A media API turns a four-minute blocking node into three short HTTP requests. n8n holds a URL and a job ID, never the file, so the event loop stays free while the encode runs. With FFmpeg Micro, the shape is the same whether you call it from an HTTP Request node, Make, Zapier, or your own code.
Submit the job:
curl -X POST https://api.ffmpeg-micro.com/v1/transcodes \
-H "Authorization: Bearer $FFMPEG_MICRO_KEY" \
-H "Content-Type: application/json" \
-d '{
"inputs": [{ "url": "gs://your-bucket/1234567890-video.mp4" }],
"outputFormat": "mp4",
"preset": { "quality": "medium", "resolution": "1080p" }
}'
You get back a job id and "status": "pending". Poll it:
curl https://api.ffmpeg-micro.com/v1/transcodes/abc123-job-uuid \
-H "Authorization: Bearer $FFMPEG_MICRO_KEY"
While it runs you see "status": "processing"; when it's done you get "status": "completed" with a completedAt. Then ask for a signed download URL:
curl https://api.ffmpeg-micro.com/v1/transcodes/abc123-job-uuid/download \
-H "Authorization: Bearer $FFMPEG_MICRO_KEY"
In n8n that's an HTTP Request node, a Wait node of 5 to 10 seconds, an IF node checking status, and a loop back to the status check. Each poll returns in milliseconds, so the worker renews its Redis lock on schedule the whole time. Polling costs nothing: checking job status, listing jobs, and downloading outputs are all free on FFmpeg Micro, and billing is one token per 10 seconds of input video, metered per second. Failed jobs are never billed. A 45-second clip costs 4.5 tokens whether the encode takes eight seconds or eighty.
The full node-by-node rebuild is in n8n 3.0 breaking changes kill your FFmpeg step. Send it HTTP. If you're still keeping a binary inside the image, Why n8n says "No usable ffmpeg was found" covers why that breaks on upgrade.
Manual FFmpeg node vs. submit-and-poll, on a queue-mode worker
The difference that matters isn't encode speed. It's how long the worker can't talk to Redis.
| FFmpeg in Execute Command / Code node | HTTP submit and poll | |
|---|---|---|
| Event loop blocked | Minutes, for the whole encode | Milliseconds per request |
| Lock renewals missed | Many (renewal is every 10s) | None |
| Worker memory | Scales with input file size | Flat, a URL and a job ID |
| Needs FFmpeg in the image | Yes, rebuild on every n8n patch | No |
| Works on n8n Cloud | No | Yes |
| Cost model | Your server's uptime | Per second of input video |
Pitfalls that bite after the upgrade
- Only the main instance got the new tag. Workers run the same image and need the same pin, or the fixed claim logic isn't where the jobs are.
- The lock duration was raised during debugging and left there. Put
QUEUE_WORKER_LOCK_DURATIONback to the 60000 default once you're on 2.45.1+, or real worker deaths go undetected that long. - Crashed executions were assumed to retry. They don't. With
maxStalledCountat 0, anything that failed on 2.45.0 has to be replayed from the executions list. - The Wait node is set to 1 second. Polling is free, but a one-second loop on a four-minute job makes 240 HTTP requests and clutters the execution. Five to ten seconds is better.
One more specific to this release: 2.45.0 made the durable scheduler the default, so "every N minutes" schedules count N from publish time, not from clock boundaries. A nightly render that looks like it moved after the upgrade is that change, not this bug.
FAQ
Does n8n 2.45.1 fix the crashed-with-null-startedAt bug, or do I need 2.45.3?
n8n 2.45.1 contains the fix, shipped October 21, 2026 as "Claim an idle worker's next queue job and its lock in one step (#41558)". 2.45.2 and 2.45.3 followed on October 22 and 23 with further patches, so go straight to the newest 2.45.x.
Can I set QUEUE_WORKER_MAX_STALLED_COUNT to work around it without upgrading?
No. n8n removed QUEUE_WORKER_MAX_STALLED_COUNT in version 2.0, and setting it on any 2.x build has no effect. There's no env-var workaround for the two-step claim race; the only remedy is running 2.45.1 or later.
Will the crashed executions re-run on their own?
Crashed executions from this bug don't re-run automatically. n8n sets maxStalledCount to 0, so a stalled job is failed rather than retried. Replay them by hand from the executions list after the upgrade.
Is this the same thing as executions stuck in "Queued" or "Running"?
Executions stuck in Queued are the opposite failure: no worker ever claimed the job, which usually points at Redis connectivity or a worker that isn't running. This bug is a worker that did claim the job and then lost it, so the status ends up crashed.
If you'd rather have a working API key and a finished transcode in the same sitting than keep an encoder inside your automation host, the quickstart runs the whole flow: it creates a temporary key, then does the presigned upload, the transcode, the poll, and the download, showing the request and response at each step. The free tier gives you 200 tokens, about 33 minutes of video, with no card.
About Javid Jamae
Founder & CEO at FFmpeg Micro
Javid is a software engineer, author, and entrepreneur with over 25 years of professional software development experience across enterprise, startup, and consulting environments. He founded FFmpeg Micro to make video processing accessible to developers through a simple, automation-first REST API.
You might also like

Reformatting isn't original. Repurpose long-form video to Shorts
YouTube now demotes template-based bulk edits. How to repurpose long form video to shorts with per-clip cuts, real 9:16 crops, and captions from each segment.

A model swap isn't the Sora API shutdown alternative for n8n
The Sora API shutdown alternative for n8n: swap in an async Veo 3.1 or Kling 3.0 call, then normalize the output with reframe, concat, captions and audio mix.

n8n Convert to File base64 video is corrupt: the data URI fix
n8n Convert to File base64 writing a corrupt video? The data URI prefix shifts every byte. The 2.45.0 fix, a Set node workaround, and the safer pattern.
Ready to process videos at scale?
Start using FFmpeg Micro's simple API today. No infrastructure required.
Get Started Free