FFmpeg "Impossible to Convert": Fix the Format, Not the Filter

Your overlay command ran fine last month. Today FFmpeg stops with Impossible to convert between the formats supported by the filter 'graph 0 input from stream 0:0' and the filter 'auto_scaler_0', followed by Error reinitializing filters! and Conversion failed!. The filter named in that message is almost never the thing you need to change.
Quick answer: The FFmpeg "Impossible to convert between the formats supported by the filter" error means two ends of one link in your filter graph accept no pixel format in common, and thescalefilter FFmpeg tried to auto-insert between them couldn't bridge the gap either. Fix it by adding an explicitformat=node on the branch that's wrong, before the filter that complained ([1]format=yuva420p[lg];[0][lg]overlay=10:10), and by pairinghwdownload,format=nv12whenever hardware frames have to meet a software filter. If you'd rather not debug format negotiation on every new input file, send the overlay to the FFmpeg Micro API as one call and let the service pick the graph.
What FFmpeg is actually telling you
FFmpeg builds a filter graph before it processes a single frame, and every link in that graph has to settle on one pixel format. Each filter publishes a list of formats it accepts through a function called query_formats. libavfilter merges the lists link by link, and where two lists don't intersect it quietly inserts a scaler to convert.
You can watch that happen. Overlaying a 200x80 RGBA PNG onto a yuv420p video with -loglevel debug prints this:
[Parsed_overlay_0] auto-inserting filter 'auto_scaler_0' between the filter
'graph 0 input from stream 1:0' and the filter 'Parsed_overlay_0'
[AVFilterGraph] query_formats: 4 queried, 2 merged, 1 already done, 0 delayed
[auto_scaler_0] w:200 h:80 fmt:rgba sar:1/1 -> w:200 h:80 fmt:yuva420p sar:1/1
Nobody asked for that conversion. FFmpeg noticed overlay wouldn't take rgba in its default yuv420 mode and turned the PNG into yuva420p on its own. The error you're reading is what happens when this rescue attempt fails: there's no format the auto scaler can produce that the downstream filter will accept.
That's why the fix is a pixel format, not a filter. The filter in the message is the one that reported the conflict, and the branch feeding it is usually the one carrying the wrong frames.
How to see which formats a filter will take
Run ffmpeg -h filter=<name> first. It won't print an exhaustive pixel format table, but for the format-sensitive filters it shows you the option that controls negotiation, which is the part you can change. For overlay:
$ ffmpeg -h filter=overlay
format <int> ..FV.... set output format (default yuv420)
yuv420
yuv422
yuv444
rgb
gbrp
Newer builds add the 10-bit variants and auto. So overlay in its default mode works in yuv420p and yuva420p, and nothing else. An rgba PNG, a gbrp frame, or a 10-bit yuv420p10le source all need converting before they reach it.
For the rest, -loglevel debug is the ground truth. It prints pixfmt: for every graph input and every fmt: the auto scaler picks, so you can read the negotiated format at each link instead of guessing at the source.
The three setups that produce this error
Three specific mismatches account for nearly every report of this error, and they're worth telling apart because the fix goes in a different place each time.
| Setup | What you see | Where the fix goes |
|---|---|---|
| RGBA or alpha source into an 8-bit yuv graph | `auto_scaler_0` named in the error, at a graph input | `format=yuva420p` on the overlay branch |
| Hardware frames meeting a software filter | Error names the hwaccel'd input, or `Query format failed` | `hwdownload,format=nv12` before the software filter |
| Filter with a narrow format list | Error names the filter itself | `format=` immediately upstream of that filter |
An RGBA logo or alpha WebM over yuv420p
An RGBA logo or an alpha WebM going over a yuv420p main video is the friendly case, and it usually resolves itself. Auto-insertion handles rgba to yuva420p on a small PNG without you noticing. It breaks when something else in the chain pins the format, such as a hardware upload, a 10-bit main input, or a second filter that only takes gbrp.
Be explicit and the negotiation stops being a guess:
ffmpeg -i main.mp4 -i logo.png \
-filter_complex "[1]format=yuva420p[lg];[0][lg]overlay=10:10" \
-c:v libx264 -pix_fmt yuv420p out.mp4
If your overlay source is an alpha WebM rather than a PNG, check that the alpha survived decoding before you touch the graph at all. A VP9 file with yuv420p instead of yuva420p has no alpha channel left to negotiate, which is a different problem covered in your FFmpeg overlay isn't broken, your transparent video is.
Hardware frames meeting software filters
Mixing -hwaccel output with a software filter is the version that fills the NVIDIA developer forums, usually under overlay_cuda or overlay_vaapi. Decoded frames stay in GPU memory as cuda or nv12 surfaces, the PNG you're overlaying lives in system memory, and no scaler on earth converts between the two. Here's the real failure on a hwaccel'd input:
$ ffmpeg -hwaccel videotoolbox -hwaccel_output_format videotoolbox \
-i main.mp4 -vf hwdownload -f null -
Impossible to convert between the formats supported by the filter
'graph 0 input from stream 0:0' and the filter 'auto_scaler_0'
Error reinitializing filters!
Failed to inject frame into filter network: Function not implemented
hwdownload needs an explicit format filter directly after it, because the formats it can output come from the hardware frames context rather than from whatever the next filter wants. FFmpeg's own hwaccel documentation says so, and it's the single most common omission:
-vf "hwdownload,format=nv12,overlay=10:10"
Going the other direction, hwupload without a device gives you a neighboring error instead: Query format failed for 'Parsed_hwupload_0': Invalid argument. That one means you skipped -init_hw_device, not that your formats disagree.
The honest cost of the GPU path is that every hwdownload/hwupload pair moves full frames across the PCIe bus, which can erase the speedup you added hwaccel for. If your pipeline overlays a static logo on 1080p clips, a software graph is often faster end to end and never throws this error.
A filter with a narrow format list
Some filters accept a short list and refuse everything else. alphaextract needs an alpha plane, premultiply needs a specific second input, and the hardware-specific filters accept only their own surface types. Feed one of these the wrong thing and the message may change:
$ ffmpeg -i main.mp4 -vf "format=yuv420p,alphaextract" -f null -
[Parsed_alphaextract_1] Requested planes not available.
[Parsed_alphaextract_1] Failed to configure input pad on Parsed_alphaextract_1
Requested planes not available is the filter rejecting the format outright. Impossible to convert is the negotiation between two filters failing. Both mean "wrong pixel format arrived here," and both are fixed by a format= node upstream.
Why the format node belongs before the overlay
Putting the conversion after the overlay makes FFmpeg do the work twice. Compare the debug output of overlay=format=rgb,format=yuv420p with the default path. The command that forces RGB converts the entire main frame on the way in and the entire composited frame on the way out:
[auto_scaler_0] w:640 h:360 fmt:yuv420p -> w:640 h:360 fmt:rgba
[Parsed_overlay_0] main w:640 h:360 fmt:rgba overlay w:200 h:80 fmt:rgba
[auto_scaler_1] w:640 h:360 fmt:rgba -> w:640 h:360 fmt:yuv420p
Two full-frame conversions per frame, where the default path converts one small PNG once. On a 30-second 1280x720 clip with a 200x80 logo and libx264 -preset veryfast, the default yuv420 path finished in about 3 seconds on my machine and the format=rgb version took 5 to 7 seconds for a visually identical result. Scale that across a few thousand clips a night and it's real money.
The rule that comes out of this: convert the smallest stream, as early as possible, and let the main video stay in its native format all the way to the encoder.
Pitfalls worth checking before you rewrite the graph
Most of the time spent on this error goes to things that were never the format at all. A quick pass through these saves the rewrite:
-pix_fmt yuv420psets the encoder input format, not anything inside the graph. It won't fix a negotiation failure between two filters.- A filter chain given to
-vfcan't span two inputs. If you're overlaying, it has to be-filter_complex. - Adding
-c copywhile filtering fails for an unrelated reason, described in filtering and streamcopy cannot be used together. - 10-bit sources (
yuv420p10lefrom HDR phone footage or some AI generators) breakoverlayin its default 8-bit mode. Either setformat=yuv420p10or convert down withformat=yuv420pfirst. - A graph that configures and then produces nothing is a different failure, covered in fix "output file is empty, nothing was encoded".
The reason this error keeps coming back in production isn't that the fix is hard. It's that the correct graph depends on what the input file happens to be, and user-uploaded video is not consistent. A batch of 200 clips can contain 8-bit yuv420p MP4s, a 10-bit HEVC from someone's iPhone, and a VP9 WebM with alpha, and the single filter_complex string you tuned last week handles exactly one of them.
That's the part worth handing off. FFmpeg Micro takes the overlay as a job: point it at your video URL and your logo, poll or take a webhook when it's done, and pixel format negotiation, hardware frame handling, and scaler placement stop being your code. There's no FFmpeg to install and no servers to run, and it works the same from n8n, Make, Zapier, or your AI agents over MCP.
FAQ
Does -pix_fmt yuv420p fix "impossible to convert"?
-pix_fmt yuv420p almost never fixes this error. That flag controls the format handed to the encoder at the end of the graph, while the error happens earlier, when two filters fail to agree. Put a format=yuv420p filter inside the graph, upstream of the filter named in the message, and keep -pix_fmt for the encoder.
Which filter named in the error should I change?
The filter named in the error is the one that reported the conflict, so treat it as the location and not the cause. When the message names auto_scaler_0 and a graph input, the branch feeding that input carries the wrong format. When it names a real filter like Parsed_overlay_0, look at what's immediately upstream of it.
Why do I need format=nv12 after hwdownload?
hwdownload needs an explicit format filter after it because the system-memory formats it can emit are decided by the hardware frames context, not by the next filter in the chain. Without that node, FFmpeg has to guess and the negotiation fails. Write hwdownload,format=nv12 as one unit and don't separate them.
Is this error a sign my video file is corrupt?
This error says nothing about file integrity. It's raised while the filter graph is being configured, before frames are processed, so a perfectly valid file will trigger it with the wrong command and a damaged file will usually fail with something else, like moov atom not found or Invalid data found when processing input.
If your overlays work on your test clip and break on real uploads, that variability is the actual problem to solve, not the graph. Sign up free and run one of your failing files through the API to see the same composite come back without the format archaeology.
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

How to Upscale Video with FFmpeg (and When It Actually Helps)
FFmpeg upscale video the honest way: the lanczos scale command for 1080p and 4K, the bitrate math that decides how it looks, and when no scaler helps.

FFmpeg 9.0 verifies TLS: fix 'certificate verify failed
FFmpeg 9.0 verifies TLS by default, so 'ffmpeg certificate verify failed' kills HTTPS inputs that worked on 8.1.2. Fixes: -ca_file, CA bundle, tls_verify.

FFmpeg CVE-2026-96611: is your self-hosted build patched?
FFmpeg CVE-2026-96611 affects every build before 9.0. How to check the version your pipeline actually runs, who's exposed, and how to patch a container.
Ready to process videos at scale?
Start using FFmpeg Micro's simple API today. No infrastructure required.
Get Started Free