A close detail of Georges Seurat's Le Chahut showing the individual dots of paint that make up the image when viewed from a distance

Seurat's Le Chahut, close enough to see the encoding. Step back and it becomes a dancer. The VAE is the step back, and it is the only part of your pipeline that ever touches an actual pixel.

Your Model Never Saw A Pixel. The VAE Did.

Everything the diffusion model does happens in a compressed code. The decoder turns that code into an image, and it is where washed colours, plastic skin and black outputs come from.

Published August 20, 2026 · RealAIGirls · About a 9 minute read

Share on X Share on Facebook Share on Reddit

You get a generation back and the pose is right, the outfit is right, the lighting you asked for is there, and the skin looks like a vinyl doll. Colours sit a half step grey. Fine hair goes to mush. So you go change the checkpoint, because the checkpoint is what people blame.

The checkpoint may have had nothing to do with it. The last piece of software that touched that picture was the decoder, and most people running these tools have never chosen one on purpose.

The Model Works In A Code, Not An Image

Latent diffusion does not denoise pixels. That was the whole idea behind it, because denoising a 1024 by 1024 image directly is enormously expensive. Instead an autoencoder compresses the image into a small numerical grid, the diffusion model does all of its work inside that grid, and a decoder expands the grid back out to pixels at the end.

The original Stable Diffusion autoencoder is called kl-f8. The f8 means it shrinks each side of the image by a factor of eight, so a 1024 by 1024 picture becomes a 128 by 128 grid. That grid holds 4 channels, which works out to roughly 48 times lossy compression. SDXL later retrained the same architecture from scratch, so it is a different set of weights doing the identical job at the identical ratio. Every SD1.5 and SDXL image you have ever made came out through that funnel.

Forty eight to one is a lot to throw away. It is enough for the model to compose a scene. It is not enough to keep a fine texture perfectly intact, which is why eyelashes, fabric weave and text have been historically painful in this generation of models.

Four Channels, Then Sixteen, Then Thirty Two

Channel count is the single most useful number to know about any VAE, because it tells you how much of the original image survives the round trip.

AutoencoderLatent channelsCompressionNotes
SD kl-f8 (1.x, 2.x)448xCarries a bright spot artifact that gets worse at higher input resolutions
SDXL VAE (0.9 and 1.0)448xSame architecture, retrained from scratch, no bright spot
SD3 VAE1612xAdds a shift factor alongside the usual scaling factor, drops the quant conv layers
FLUX.1 VAE1612xSame config as SD3, higher decoding quality
FLUX.2 VAE326xSmallest compression factor of any of them, normalisation baked into the checkpoint

Going from 4 channels to 16 is why Flux and SD3 hold small text, fine lace and individual hairs so much better than SDXL ever did at the same resolution. It has very little to do with the transformer and a great deal to do with the funnel being four times wider.

This is also the one number you cannot change on your own. The diffusion model was trained against a specific latent space. A 16 channel VAE bolted onto a 4 channel model does not produce a better image, it produces noise, because the two halves are speaking different languages.

The Black Image Bug Nobody Explains

If you have ever run SDXL and received a solid black image or a screen full of coloured garbage, this is almost certainly what happened.

The original SDXL VAE produces NaNs in fp16 because its internal activation values are too large for half precision to hold. The numbers overflow, the overflow propagates, and what comes out the other end is not an image.

A community finetune called sdxl-vae-fp16-fix solves it by keeping the final output the same while scaling down the weights and biases inside the network so nothing overflows. It is 83.7 million parameters, MIT licensed, and running roughly 300,797 downloads a month at the time of writing, which tells you how common the problem is.

Quality cost is close to nothing. Measured against the original running in fp32, the fixed version scores 0.056 on LPIPS against 0.055, and 0.73 on SSIM against 0.73. If you are on SDXL in half precision and you have not swapped this in, do it before you change anything else.

Why Faces Improved On SD1.5 In 2022

One other decoder is worth knowing by name, because most SD1.5 workflows quietly load it: vae-ft-mse-840000-ema-pruned. The number in the filename is the training step count.

Stability finetuned the original kl-f8 decoder twice. The first pass, ft-EMA, kept the original loss configuration of L1 plus LPIPS. The second, ft-MSE, resumed from that checkpoint and ran another 280,000 steps to reach a total of 840,001, this time with a loss weighted toward mean squared error at MSE plus 0.1 times LPIPS. The training set was a one to one mix of LAION-Aesthetics and an unreleased LAION-Humans subset, chosen specifically to make faces reconstruct better.

Measured on COCO 2017, ft-MSE against the original: rFID 4.70 against 4.99, PSNR 24.5 against 23.4, SSIM 0.71 against 0.69, PSIM 0.92 against 1.01. Every one of those is an improvement, and the entire cost is loading one extra file. The licence is MIT.

There is a real trade between the two finetunes. ft-MSE gives smoother output. ft-EMA keeps more high frequency texture. If you shoot portraits where skin should read as skin and not as porcelain, try ft-EMA before you assume the smoother one is the better one.

What To Actually Change

Four practical rules come out of all of this.

Match the decoder to the architecture, always. SD1.5 VAEs go on SD1.5 models, SDXL VAEs go on SDXL models, and Flux ships its own. There is no cross architecture upgrade path.

Most checkpoints have a VAE baked in already, and it is frequently a bad one that the merger inherited from somewhere and never thought about. If your colours look grey and desaturated across every prompt and every seed, that baked decoder is the first suspect, not your prompt.

If you get a black image on SDXL, it is the fp16 overflow. Load the fixed VAE or force the decoder to run in fp32.

And when you want to know whether a VAE is doing anything for you, test it the only way that proves anything: fix the seed, fix the prompt, generate once, then decode the identical latent through both decoders and put the two results side by side at 100 percent zoom. Look at hair, eyelashes, fabric and any text. That is where the difference lives, and it is invisible at thumbnail size.

The Honest Counterpoint

The VAE is the smallest lever in the entire stack, and it gets blamed for a lot of things it did not do.

A decoder cannot fix composition. It cannot fix anatomy. It cannot fix a prompt that was vague about lighting. If your image is wrong in a way you could describe in words to another person, the VAE is not your problem and swapping it will waste an afternoon. The visible effects are narrow: colour cast, fine texture, and the specific failure modes described above.

More channels is not free either. A 16 or 32 channel latent costs more memory and more compute for every step of every generation, and on modest hardware that trade is genuinely arguable. The reason people running Flux need more VRAM than people running SDXL is not entirely the transformer.

And there is a real risk in treating VAE swapping as tuning. Every extra encode and decode cycle degrades an image slightly, so a workflow that round trips through the decoder four times to apply four different tweaks will look worse than one that does the work in latent space and decodes once. The decoder is a door, not a filter. Walk through it as few times as you can.