You queue a prompt, wait for the sampler to finish, and the saved PNG is pure black. No crash, no red node, no OutOfMemory — just a silent, useless output that looks like it rendered something and then collapsed into zeros. If that describes you, you are hitting one of the most confusing failure modes in ComfyUI: a latent tensor full of NaN (not-a-number) values that the VAE then decodes into an all-black image.
This is a precision problem, not a prompt problem. Your diffusion model isn’t producing a bad image — it’s producing a broken tensor, and ComfyUI is faithfully converting that garbage into black pixels. Below I walk through how to confirm the diagnosis, the three realistic root causes, and the exact launch flags and VAE swaps that resolve each one.
The One-Line Warning That Proves the Diagnosis
Before touching anything, open the terminal that launched ComfyUI and read it. The smoking gun for this failure is a single RuntimeWarning:
RuntimeWarning: invalid value encountered in cast
img = Image.fromarray(np.clip(i, 0, 255).astype(np.uint8))
That line is the whole story. The sampler produced NaN (or Inf) values in the latent, and when ComfyUI cast those to an 8-bit image, every pixel collapsed to zero. Sometimes the result is gray or has a faint green wash instead of pure black, but the root cause is the same family of problems, and almost all of them are precision-related.
If you see invalid value encountered in cast, the latent was already corrupt before the VAE decoded it. That points the finger at precision in the diffusion model (UNet) or the VAE, which is exactly what the fixes below address. ComfyUI’s own VAE flag help text says the quiet part out loud: the fp16 VAE flag is documented as potentially causing black images. Half precision is the usual culprit.
If you see no warning at all and just a silent black PNG, don’t rule this out — several 2026 reports reproduce exactly that on brand-new model architectures. The diagnostic steps are the same; you just lose the convenience of the one-line confirmation.
Root Cause 1 — The SDXL fp16 VAE NaN Bug
This is the single most common cause for anyone running SDXL or an SDXL-based checkpoint. The original SDXL VAE that Stability shipped numerically overflows in fp16: certain activations exceed the fp16 numeric range, become Inf, then NaN, and you get a black image. It is not your GPU — that specific VAE is simply unstable in half precision.
There are three fixes, in order of preference:
Option A — Swap in the fp16-safe VAE (best)
Download sdxl-vae-fp16-fix, a retrained version of the SDXL VAE that stays inside fp16 range without producing NaNs. Place sdxl_vae_fp16_fix.safetensors into ComfyUI/models/vae/, add a Load VAE node, point it at that file, and wire it into your VAE Decode. This keeps the speed and low VRAM of fp16 while eliminating the black images. The widely used madebyollin/sdxl-vae-fp16-fix on Hugging Face was created specifically to solve this, and community reports are consistent that it works.
Option B — Force the VAE to fp32
Launch ComfyUI with:
python main.py --fp32-vae
This runs the VAE in full precision. No NaNs, slightly more VRAM, and a little slower on decode — but it always works. On a 24GB card the cost is negligible.
Option C — Run the VAE on CPU
If you are VRAM-starved and fp32 VAE tips you into an out-of-memory error, you can offload the decode entirely:
python main.py --cpu-vae
This reliably eliminates the SDXL black-image issue. It is slow — decode can take several seconds instead of a fraction of one — but it is bulletproof when nothing else fits.
Root Cause 2 — The Wrong (or Missing) VAE for Your Model
If there is no Load VAE node in your workflow, ComfyUI uses whatever VAE is baked into the checkpoint. If that VAE is missing or mismatched, you get black or garbage output. The mismatch that bites people most is using an SD 1.5 VAE with an SDXL model, or vice versa. They are not interchangeable.
The fix is to add an explicit Load VAE node and point it at the correct file for your model family:
- SDXL / SDXL checkpoints →
sdxl_vae.safetensors(or the fp16-fix version from Root Cause 1) - SD 1.5 checkpoints →
vae-ft-mse-840000-ema-pruned.safetensors - FLUX →
ae.safetensors(never reuse an SD or SDXL VAE)
One more trap worth a quick check: make sure the VAE file actually exists in ComfyUI/models/vae/ and isn’t a zero-byte or truncated download. An empty VAE file decodes to black every time.
Root Cause 3 — The GTX 16-Series fp16 Trap (and New Model Architectures)
This one is hardware-specific. The GTX 1650 / 1660 / 1660 Ti / 1660 Super cards have a known defect in fp16 support — they produce an all-black or all-green image in half precision unless you force full precision. ComfyUI maintainers and a long-running issue thread confirm the behavior: on a 16-series card, fp16 is unreliable across the board.
The fix is a single flag:
python main.py --force-fp32
This sets the UNet, VAE, and text encoder all to fp32. It is the most accurate and slowest path, but on these cards it is the only stable option. Expect noticeably slower generation — the 16-series was never a fast inference card to begin with.
The same pattern shows up on very new architectures before their fp16/bf16 paths stabilize in ComfyUI. The clearest recent example is Z-Image Base, which produced silent black images regardless of precision until an upstream fix landed. If you are running a brand-new model and the Turbo variant works but the Base variant is black, that is a strong signal the problem is upstream and not your setup. In those cases, forcing bf16 on the UNet often helps, because bf16 has a much wider exponent range than fp16 and survives the overflows that kill it — on RTX 30/40/50-series cards bf16 is nearly free.
A Reliable Diagnostic Order
When a black image appears, work through this checklist instead of guessing:
- Read the terminal. Confirm
invalid value encountered in castor a NaN message. No NaN message → it may still be this problem, but rule out a simple preview/display issue first by opening the saved PNG outside ComfyUI. - Identify the model. SDXL → almost certainly Root Cause 1. Brand-new architecture → Root Cause 3. SD 1.5 that worked yesterday → check you didn’t change the VAE or CFG.
- Identify the card. GTX 16-series →
--force-fp32, immediately. Everything else → a precision flag on the VAE first. - Apply one flag at a time and restart. ComfyUI reads launch flags at startup, so a flag change means a full restart of the process — refreshing the browser tab does nothing.
A note on choosing the flag: if you have the choice, bf16 is usually the better fix than fp32. bf16 (--bf16-vae, --bf16-unet) keeps the wide numeric range that prevents NaN overflow but uses half the memory and runs faster than fp32. Every RTX 30-, 40-, and 50-series card supports it natively. Reach for fp32 (--force-fp32, --fp32-vae) only when bf16 still misbehaves, or on older cards where bf16 support is weak or absent.
Common Pitfalls That Waste Time
Two mistakes come up again and again in the issue threads:
Assuming it’s the VAE when it’s actually the UNet. If you add the fp16-fix VAE and the image is still black, your problem isn’t the VAE — the UNet is producing NaNs upstream. The fp16-fix VAE only solves VAE overflow; if the latent is already NaN before decode, you need a precision flag on the UNet instead.
Changing the wrong thing and masking the signal. When debugging, change one variable at a time. Start from a known-good official workflow for your model, then reintroduce LoRAs, custom samplers, and precision flags one by one. If a black image appears only after a specific change, that is far more informative than toggling five settings at once.
There’s also a hardware-adjacent tail case worth knowing about. A persistent, non-deterministic black-image regression that survives across clean installs, driver changes, and even different operating systems has occasionally traced back to failing VRAM rather than software. If every software fix fails and the problem worsens at higher resolutions, a VRAM stress test like OCCT can help rule that out before you waste more hours — though this is the rare outcome, not the default.
Verify the Fix and Move On
After applying a precision fix, verify it holds rather than trusting a single lucky run. Generate a small batch (three to five images) at your target resolution. The black-image bug is often intermittent — several reports describe a batch where only some images come out black. A fix that produces clean output across a full batch, at the resolution that was triggering failure, is a real fix.
Your verification checklist is short:
- A clean batch at the previously failing resolution
- No
invalid value encountered in castin the terminal - The correct VAE and precision flags recorded so you can reproduce the working setup
Once those hold, you have a stable pipeline again. The key to this whole failure mode is remembering that a black image is a precision problem first and foremost — and ComfyUI almost always tells you exactly what went wrong, if you know which warning line to look for.
For more on keeping ComfyUI stable under memory pressure, see our guide on fixing ComfyUI VAE decode out-of-memory errors and the breakdown of attention backends that affect speed and VRAM. The full list of launch flags and their memory behavior lives in the official ComfyUI troubleshooting documentation.
Leave a Reply