n8n 3.0 breaking changes kill your FFmpeg step: what to change

You upgraded a self-hosted n8n instance to 3.0, or you're about to, and the video step is the part that won't survive. Four entries on n8n's breaking-changes list land on the same node chain, and because they're documented subsystem by subsystem, nobody reading that page sees them add up.
Quick answer: Four n8n 3.0 breaking changes hit a self-hosted FFmpeg workflow at once: the Read Binary File, Read Binary Files and Write Binary File nodes are removed, the task runner timeout default drops from 300 seconds to 60, the decompression cap falls from 2 GiB to 256 MiB, and unverified community packages stop loading. Swap the removed nodes for Read/Write Files from Disk, and setN8N_COMPRESSION_NODE_MAX_DECOMPRESSED_SIZE_BYTESandN8N_UNVERIFIED_PACKAGES_ENABLEDback explicitly if you need the old behavior. The 60-second runner clock has no local fix for a real encode, so move the encode off the automation host: one HTTP Request to FFmpeg Micro submits the job, then n8n polls or takes a webhook and downloads the output. No binary on disk, no runner clock ticking.
The four n8n 3.0 changes that land on one video chain
The workflow shape that takes all four hits is the self-hosted DIY pattern: HTTP Request downloads a source file, Write Binary File drops it in /tmp, Execute Command shells out to ffmpeg, Read Binary File picks the output back up. n8n's v3.0 breaking changes page puts the release in October 2026, and the project's DEVELOPING_V3.md calls v3 "an operational release: breaking changes, removals, and legacy cleanup." That's policy, not accidents waiting to be walked back. Version 2.43.0 shipped on October 6 as the last 2.x feature release, so the window for auditing is now.
| Change | 2.x | 3.0 | Effect on a video step |
|---|---|---|---|
| Binary file nodes | Read/Write Binary File | Removed (~32 nodes total) | The file handoff to FFmpeg stops existing |
| `N8N_RUNNERS_TASK_TIMEOUT` | 300 seconds | 60 seconds | Any encode over a minute is killed mid-flight |
| `N8N_COMPRESSION_NODE_MAX_DECOMPRESSED_SIZE_BYTES` | 2 GiB | 256 MiB | Asset bundles and B-roll zips fail to unpack |
| `N8N_UNVERIFIED_PACKAGES_ENABLED` | `true` | `false` | Your FFmpeg community node silently stops loading |
n8n read write binary file: the nodes are removed, not renamed
Read Binary File, Read Binary Files and Write Binary File are deleted in 3.0. The replacement is Read/Write Files from Disk, which absorbed their operations back in 1.21.0, and n8n's integrations page still describes that as a fold-in from five versions ago, which reads like a cosmetic deprecation. In 3.0 the old nodes don't load at all, so a workflow JSON that references them breaks on import.
The swap is mechanical. The old chain:
1. HTTP Request GET source.mp4, response: binary
2. Write Binary File /tmp/in.mp4
3. Execute Command ffmpeg -i /tmp/in.mp4 -c:v libx264 -crf 23 -vf scale=-2:1080 -c:a aac /tmp/out.mp4
4. Read Binary File /tmp/out.mp4
Replace both ends with Read/Write Files from Disk: one node with the Write operation and File Path /tmp/in.mp4, one with Read and /tmp/out.mp4. Export your workflows and check them first. The Migration Report under Settings lists removed nodes, and n8n-sunset scans exported JSON offline with --target 3.0, so a CI job fails before the upgrade does.
A second problem sits in the middle of that chain. The Execute Command node has been disabled by default since n8n 2.0 on security grounds, so for many self-hosters the FFmpeg call died a release line ago. We wrote up that break in n8n disabled the Execute Command node.
n8n FFmpeg timeout: which clock actually fired, and why 300 doesn't fix it
Three timeouts can kill a video step in n8n, and the error text doesn't say which one fired. N8N_RUNNERS_TASK_TIMEOUT is how long an accepted task may run before the runner is stopped and restarted. N8N_RUNNERS_TASK_REQUEST_TIMEOUT is the 60-second window a task waits for a free runner. EXECUTIONS_TIMEOUT caps the whole workflow execution. 3.0 changes the first one, dropping the default from 300 seconds to 60, per n8n's task runners reference.
A community thread on runner timeouts documents the trap that makes this hard to diagnose: the broker and the runner process can disagree, the main instance advertising 300 seconds while the runner enforces 60. The effective limit is the lower of the two. That was an edge case before 3.0, and 3.0 makes it the default everywhere.
You can set N8N_RUNNERS_TASK_TIMEOUT=300 and carry on, but that moves the failure instead of removing it. The encode still runs on the automation host, holding the source and the output in that box's RAM and disk, competing with every other execution. One 1 GB input through Read Files from Disk is enough to OOM a small instance, the failure mode behind the classic "my n8n restarts during video jobs" report.
Past a short clip there's no local workaround, because the constraint isn't the number in the env var. It's that a CPU-bound media job runs inside a process built to dispatch webhooks. The structural fix gets the bytes and the clock off the box: submit the encode to an API and let n8n hold a job ID. That's what FFmpeg Micro does from a plain HTTP Request node, and nothing in the workflow runs longer than the request that starts the job. Transcription has the same shape, covered in large video transcription in n8n fails.
Local command and one-call API, same work:
# Local: needs ffmpeg on PATH, /tmp space, and under 60s of runner time
ffmpeg -i /tmp/in.mp4 -c:v libx264 -crf 23 -c:a aac /tmp/out.mp4
// n8n HTTP Request node, POST https://api.ffmpeg-micro.com/v1/transcodes
// Header: Authorization: Bearer YOUR_API_KEY
{
"inputs": [{ "url": "gs://your-bucket/1234567890-video.mp4" }],
"outputFormat": "mp4",
"options": [
{ "option": "-c:v", "argument": "libx264" },
{ "option": "-crf", "argument": "23" }
]
}
The response comes back immediately with {"id": "job-uuid", "status": "pending"}. A Wait node plus a GET on /v1/transcodes/{id} polls until status is completed, then /v1/transcodes/{id}/download returns a signed URL. Inputs longer than two minutes run in a separate long lane, so a 20-minute encode can't queue behind anything on your side. -filter_complex isn't supported; use the preset resolution and the overlay options instead.
The 256 MiB decompression cap and the unverified-packages default
N8N_COMPRESSION_NODE_MAX_DECOMPRESSED_SIZE_BYTES falls from 2 GiB to 256 MiB, and N8N_COMPRESSION_NODE_MAX_ZIP_ENTRIES from 5,000 to 1,000. If your faceless-channel workflow unzips a stock-footage pack or a batch of client uploads, set 2147483648 and 5000 explicitly in your env to keep today's behavior. Neither the Migration Report nor an offline JSON scan can warn you, because breaching the cap depends on the size of the zip at runtime, not on anything in the workflow.
N8N_UNVERIFIED_PACKAGES_ENABLED flips from true to false, so an npm community node stays installed after the upgrade but no longer loads. Your FFmpeg node hasn't been removed, it's switched off, and N8N_UNVERIFIED_PACKAGES_ENABLED=true brings it back. Whether you should is the real question. n8n's verification guidelines forbid run-time dependencies, so a node wrapping an FFmpeg binary can never be verified, and the initial verified set was around 25 packages. That's a narrow allowlist, not a mild filter, and leaving the flag on permanently opts every unverified package on the instance back in to get one video node working.
That node probably wasn't shipping FFmpeg anyway. A fix merged on October 2, 2026 in the n8n-nodes-claudecode node documented that n8n's community installer strips optionalDependencies before installing a package, so the node's bundled Linux FFmpeg builds never arrived and video steps failed with "No usable ffmpeg was found." The finding generalizes: a community node can't ship a platform binary through n8n's installer, so every node promising local video processing is really promising a server-level FFmpeg install.
Pitfalls that bite during the upgrade itself
Most of the upgrade pain for video workflows isn't in the workflow JSON, it's in the host configuration around it:
~/.n8n/binaryDatais renamed to~/.n8n/storageon first start. If your Docker volume mounts the old path, mount the new one or setN8N_STORAGE_PATH.N8N_DEFAULT_BINARY_DATA_MODE=defaultis no longer valid, and those instances switch to filesystem mode. Check the disk has room for every execution's binaries.- Self-hosted n8n is Docker-only from 3.0; npm and npx installs are discontinued. If
ffmpegwas on the host PATH and Execute Command found it there, it won't be in the container. - The official n8n Docker image went distroless in 2026, so
apk add ffmpegin a derived image fails. We walked through this in how to use FFmpeg in n8n without touching your Docker image. - Pin the image tag instead of tracking
latest, and back up all of~/.n8nincluding hidden files before the first 3.0 start.
When keeping FFmpeg local is still the right call
Running FFmpeg on your own box makes sense for jobs that finish in a few seconds and touch small files: reading metadata, pulling a single thumbnail, remuxing a 10-second clip, stripping an audio track. Those fit inside 60 seconds of runner time and don't need an upload round trip. If you want zero per-job cost and you're willing to own a queue, workers and an object store, a self-hosted media container is a legitimate choice. Just price the ongoing maintenance: the distroless break and the optionalDependencies finding both arrived in the last four months, and both silently invalidated published advice.
FFmpeg Micro's free tier gives a new account 200 tokens, about 33 minutes of video, with API access and no card. One token buys 10 seconds of input, metered per second with no rounding up to the minute, so trimming a 30-second clip out of a one-hour recording bills 30 seconds. Status checks, job lists and downloads are free, failed jobs are never billed, and paid plans start at $19.99 a month for 2,500 tokens.
FAQ
Does the n8n Migration Report catch the video-specific breakage?
The Migration Report in Settings finds removed nodes and node versions in your workflow JSON, which covers Read Binary File and Write Binary File. It can't see runtime limits, so a chain that will blow the 60-second runner timeout, or a 400 MB zip that will hit the 256 MiB decompression cap, passes the audit and fails in production.
My FFmpeg community node disappeared after upgrading to n8n 3.0. Is it uninstalled?
The package is still installed, and n8n 3.0 stopped loading it because N8N_UNVERIFIED_PACKAGES_ENABLED now defaults to false. Setting it back to true restores the node and re-enables every other unverified package on the instance. No FFmpeg-wrapping node can ever be verified, because n8n's verification guidelines forbid run-time dependencies.
What replaces Write Binary File if the video never touches disk?
Nothing has to replace Write Binary File when the encode happens off-box: the HTTP Request node sends a JSON body with the input URL and the FFmpeg options, and n8n holds a job ID instead of bytes. The output comes back as a signed download URL, so Read Files from Disk drops out of the chain too. Same pattern as convert MP4 to GIF in n8n without a community node.
Is n8n 3.0 really Docker-only for self-hosting?
Self-hosted n8n requires a Docker-based deployment from 3.0 onward, and npm and npx installation is discontinued. Anyone who ran npx n8n on a host with ffmpeg on the PATH loses that path to FFmpeg entirely.
If the one job you need off your box is a transcode, the FFmpeg Micro quickstart shows whether the offload works for your file: sign up and the dashboard creates a temporary API key, then runs presigned upload, transcode, poll and download for you, showing the request and response at each step. Copy those four calls into HTTP Request nodes and your video step stops caring which n8n version you're on.
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

Why n8n says "No usable ffmpeg was found" and what to do about it
"No usable ffmpeg was found" in n8n means the server has no FFmpeg binary, and n8n's installer makes it impossible for a community node to ship one. Three real fixes.

n8n 3.0 breaking changes kill your FFmpeg step. Send it HTTP.
n8n 3.0 breaking changes kill the npx + host ffmpeg video step. Here's the Docker Compose and distroless Dockerfile that work, and the HTTP alternative.

Replace audio in video by API: the mux is the easy part
Replace audio in video API or FFmpeg CLI: measure drift with ffprobe, pad or trim instead of atempo, and re-burn captions against the new TTS timings.
Ready to process videos at scale?
Start using FFmpeg Micro's simple API today. No infrastructure required.
Get Started Free