Nodes/HALO Debug Pack/HALO VAE Decode (FP32)
ComfyUI Node

HALO VAE Decode (FP32)

Black images on AMD? This VAE Decode forces FP32 and tells you why

By bkpaine1·Created 7 months ago·Updated 7 months ago· 3
HALO VAE Decode (FP32)
  • samples
  • vae
  • IMAGE

This is the node the pack is named for, and it's the one you actually reach for. If you're on an AMD ROCm card and your images keep coming out black with a RuntimeWarning: invalid value encountered in cast in the log, swap your normal VAE Decode for this one. It forces the whole decode into FP32 and shouts what happened into the terminal along the way.

The backstory matters. The VAE is the codec that turns the latent (the compressed representation the diffusion model works in) back into pixels - without it there's no viewable image at all. On some hardware, especially the AMD Strix Halo APUs with unified memory this pack was built on, the VAE runs in bf16, and when a bf16 tensor gets converted to numpy for image output the cast silently fails. The README calls numpy's lack of native bfloat16 support "the elephant in the room," and it's a real, recurring complaint in the community - you don't have to own a Strix Halo to hit it.

How it works

Normal VAE Decode trusts ComfyUI's dtype handling. This one doesn't. Looking at the source, the node:

  1. Logs the incoming latent's dtype, shape, min, and max - and warns if it's a "dead" (all-zero) latent.
  2. Saves the VAE's current dtype, then casts the entire first_stage_model to FP32.
  3. Converts the latent to FP32, decodes it under torch.no_grad(), and pushes the result through the VAE's normal output processing.
  4. Restores the original dtype in a finally block, so your VAE is left exactly as it was.
  5. Prints a final verdict: NaN, black, or ✓ Output looks valid!.

There's also a nicety for video latents - if the VAE is a 2D video VAE and the latent is 5-dimensional, it slices to the first frame before decoding.

Inputs and outputs

  • samples (LATENT, required) - from your sampler.
  • vae (VAE, required) - from your VAE loader.
  • Output: IMAGE, ready for a Save Image / Preview node.

It's a drop-in replacement for the stock VAE Decode. Same two inputs, same one output, same wiring.

Installation

Part of the HALO Debug Pack. ComfyUI Manager → search "HALO Debug Pack", or:

cd ComfyUI/custom_nodes
git clone https://github.com/bkpaine1/halo_pack

Restart ComfyUI and it appears under the HALO category. No model downloads, no requirements.txt - the pack is a single file, so install is genuinely trivial.

Where people get burned

  • The diagnostics are in the terminal, not the UI. Every [HALO-VAE] line prints to the console where you launched ComfyUI. If you use a launcher that hides it, you'll miss the whole story.
  • It fixes the cast bug, not upstream NaN. If the node reports NaN in its output, the damage happened earlier - the latent or model is already poisoned, and FP32 decoding can't resurrect it. That's the moment to check the Latent Debug node and the --force-fp32 launch flag.
  • There's a small cost. Casting the VAE to FP32 and back every run adds overhead, and the VAE can use noticeably more memory in FP32. On a 128 GB Strix Halo that's nothing; on a tight 8 GB card it's a real consideration.

If your black image came from the bf16-to-numpy path specifically, this node is the fix. If it didn't, it'll tell you that too - honestly, which is more than most workarounds do.

CategoryHALO

Inputs (2)

NameTypeDefaultDescription
samplesLATENT
vaeVAE

Outputs (1)

NameTypeDescription
IMAGEIMAGE