There Is No Safe Setting for 4-Bit Quantization. There Is One Per Model.
A reproducible ComfyUI method for finding where quantization breaks your model, plus the two silent failures that make a converted file look like a bad prompt.
Someone published three quantized builds of the same 1.3-billion-parameter video model this month, sized 2.15, 2.11 and 2.07 GiB. The largest one matches its full-precision reference across six seeds. The middle one keeps the subject and turns everything else to painterly smear. The smallest, which saves 3.7% more disk, is coloured wreckage in every frame.
All three load without an error. All three dispatch to the native four-bit kernel. All three pass every structural check the tooling knows how to run.
The person who made them shipped all three on purpose, labelled the bad ones "AN EXAMPLE OF WHAT NOT TO DO," and published a written prediction he had made beforehand that turned out to be wrong. That repository is the most useful thing I have read about local model compression this year, and it has two stars.
The thing everyone gets wrong about quantization defaults
Here is the assumption almost every converter tutorial rests on: that a quantization format has a quality threshold. Below some error level it works, above it, it breaks, and the converter's default sits somewhere sensible in between.
That assumption is false, and the failure mode it produces is the worst possible shape. Not a crash. Not a warning. A file that loads, runs at the right speed, and renders something subtly wrong that you will blame on your prompt.
The bench I mentioned measures this properly. It defines "effective error" per layer, on the real activations that layer saw during sampling, against the format that layer actually received. Then it renders. Here is where three model families land:
| Model | Parameters | Tolerated | Not tolerated |
|---|---|---|---|
| Wan 2.1 VACE | 1.3 B | 0.0546 | 0.0793 |
| Z-Image v2 | ~6 B | 0.1421 | 0.1848 |
| HunyuanVideo 1.5 family | ~13 B | 0.1837 | 0.2147 |
Read the middle two rows against each other. An error of 0.1848 destroys the 6B model. An error of 0.1837 is fine on the 13B one. Those numbers sit 0.6% apart and land on opposite sides of the line, because the line belongs to the model, not the format.
Now the practical part. ComfyUI's converter has a --promote-error flag that decides which layers get promoted out of four bits. The commonly used value is 0.15. The bench author's own summary of what that does to Wan 2.1 VACE: it "writes a file here that loads cleanly, dispatches natively, passes every structural check, and renders a smear."
A default picked once on a 6B model, carried everywhere since, destroys a 1.3B one.
Two silent failures worth more than the threshold
The threshold work is the headline. These two are what will actually bite you this month.
Your Blackwell card may be faking it
ComfyUI's native convrot_w4a4 format applies a Hadamard rotation before the four-bit multiply, which is the right technique. It also has a hardware gate. Two people documented this independently, three days apart, working on different models.
The first, in the Wan bench's environment notes: "Native INT4 MMA needs major == 8 (Ampere / Ada). Hopper and Blackwell are routed to an INT8 branch deliberately."
The second, in a methodology document published September 2 by a different quantizer working on MiniMax H3, is blunter. ComfyUI-native convrot_w4a4 "dequantizes to bf16 on Blackwell. comfy_kitchen's convrot kernel gates on sm_8x, so sm_120 (Blackwell) falls back to a dequant GEMM." And then the sentence that should make you check your own setup: "It only looked the same speed because the workload is attention-bound."
So if you bought an RTX 50-series card and downloaded a ConvRot W4A4 checkpoint, you may be paying the full quality cost of four-bit weights while the math runs in bf16 anyway. The workload hides it. Attention dominates the wall clock, so the GEMM falling back to a wider path barely moves the timer, and everything looks fine.
That is a genuinely unpleasant deal: the newest, most expensive consumer hardware gets the worst version of the format, and nothing in the interface says so.
A rotated base silently ruins your LoRAs
Rotation works by multiplying the weights by a Hadamard matrix so per-channel outliers spread out instead of dominating the four-bit grid. The trade is that the weights now live in a different basis than the one they were trained in.
Your LoRAs were trained against the original basis. Nothing in the stack checks this.
The clearest statement of it I have found is on a MiniMax H3 style LoRA card from August 31. The author lists the base checkpoints that break his adapter: *_int8_convrot, nvfp4, w4a8. Then: "The LoRA loads without any error and then produces warped faces, melting limbs and disappearing objects." And, because he checked, he names the default checkpoint in the official ComfyUI H3 tutorial as minimax_h3_fl2va_pruned_int8_convrot, and says outright that you must change it.
He is explicit that this is not specific to his LoRA. It is true of MiniMax H3 adapters generally, and the mechanism generalizes to any rotated base. If you upgraded to a smaller checkpoint this year to fit your card, and you also have a folder of style adapters, you may have already been getting degraded output for months while adjusting your prompts to compensate.
Put this into practice
This procedure takes an evening the first time and about twenty minutes on every model after. You need ComfyUI, the model you care about in its original precision, and enough disk for three converted copies.
1. Establish a real reference before you compare anything to it.
This is the step the bench author got wrong first, published, and then corrected on September 1. His original renders ran at cfg 1.0 with no sigma shift and no negative prompt, which is a distilled model's operating point. Wan 2.1 is not distilled. Without guidance it drifts, so his full-precision reference came out with melted faces too, and everything measured against it was measured against garbage.
Use your model's actual operating point. For Wan 2.1 VACE that turned out to be uni_pc with the simple schedule, 25 steps, cfg 6.0, ModelSamplingSD3 shift 8, and a real negative prompt. For a distilled four-step model it will be cfg 1.0 and euler. Get this right first or nothing downstream means anything.
2. Convert at three thresholds, not one.
Pick your converter's default, then one clearly tighter and one clearly looser. The bench's three Wan builds landed at effective errors of 0.0546, 0.0793 and 0.1602, with 2, 134 and 300 of the 300 linear layers at four bits respectively. That spread is what lets you bracket the break instead of guessing at it.
3. Render the same prompt at the same six seeds through every build, including the reference.
Six seeds, not one. A single seed will show you a fluke in either direction. Then put the frames in a grid and look at them. That is the measurement.
4. Confirm the quantized math is actually running.
The bench ships probe_quant_dispatch.py --forward-only for this. On a real load and a real forward it counted 300 quantized modules, 12 of 12 forwards running quantized math, zero calls to dequantize, linear_dtype int4, and the implementation resolving to comfy_kitchen.backends.cuda. If yours shows dequantize calls, you are in the Blackwell fallback described above and your quality-versus-speed trade is not the one you think it is.
One thing not to panic about: loading these files prints WARNING: unet unexpected [...comfy_quant] for all 300 layers. The author checked, and it is cosmetic. The tensors are consumed before the check runs and complained about afterwards.
5. Keep one unrotated base for adapter work.
This is the cheap half of the whole exercise. Hold on to a bf16 or fp8 checkpoint and use it whenever a LoRA is in the graph. Use the four-bit build for base renders with no adapters. The disk cost is one extra file, and it saves you from the failure mode that has no error message.
6. Do not read divergence numbers as quality.
The single most useful correction on that bench page: when the sampler regime was fixed, the good build's mean divergence from the reference rose from 0.2936 to 0.4750 while the picture got dramatically better. Higher guidance separates trajectories, so that distance measures trajectory, not fidelity. His conclusion, and mine: "Do not compare divergence numbers across sampler settings, and do not read them as quality."
Honest limitations
The evidence base here is thin and the authors say so. The Wan measurements are one prompt, three to six seeds, 480x480, 33 frames, one scheduler, one card, and no perceptual metric at all. "Good," "smeared" and "destroyed" are the judgement of a person who looked at the pictures. The size monotonicity across three model families rests on three data points, and the page states outright that "the next model may break it the way this one broke the last."
The bench's own history is a warning about running this carelessly. Two dated corrections sit on that page. The first is the sampler-regime error above. The second: an earlier version of the threshold table credited a break to Z-Image, naming a checkpoint called capybara_v0.1 as part of that family. Read from the file, it has 1364 tensors and 54 double_blocks, which is HunyuanVideo 1.5's architecture, not Z-Image's 453 tensors and zero. The row moved and one cell of the table became honestly empty.
There is also a trap specific to VACE checkpoints that has nothing to do with quantization and will waste your renders anyway. Sampled without a VACE control node, ComfyUI's own defaults destroy the output. WAN21_Vace.extra_conds fills vace_frames with zeros when no conditioning is supplied, then runs them through process_latent_in, which subtracts the latent format's mean, so zero stops being zero. It concatenates an all-ones mask and applies the result at full strength. That is not "no control." It is a constant control at maximum, and the unquantized FP16 original fails identically. Drive vace_strength to 0 or use a real control node.
One more thing worth knowing before you quote a speed number at anyone. On the same file and the same card, the quantized build ran 1.78x slower at one frame (0.363 versus 0.204 s/step) and 1.33x faster at 33 frames (0.653 versus 0.870). The four-bit kernel carries a fixed per-layer cost that a tiny batch cannot amortise. Any speed ratio for this format is meaningless without the batch size attached.
One reading trap in the other source, which I fell into myself before checking. The rotated NVFP4 H3 work ships two lines, and their numbers differ: the base eight-step build is 12.5 GB at 13.6 GB peak VRAM, the four-step FastH3 build is 12.8 GB at 13.7 GB, because the latter bakes in a rank-32 AdaLN the former does not. Both model cards agree with the shared methodology document. If you see two figures quoted for "the H3 rotated NVFP4 file," they are two files, not a contradiction, and which one you want depends on whether you would rather have four steps or the sharper render.
What I would actually like to see
The measurement itself is not hard. Three conversions, six seeds, one grid, one dispatch probe. The reason almost nobody does it is that quantization has been framed as a solved preprocessing step rather than a decision with a per-model answer, and the tooling reinforces that by shipping a default.
What is missing is a shared table. If fifty people ran this procedure on the models they actually use and posted two numbers each, the tolerated error and the one that broke, we would know within a month whether the size monotonicity holds or whether it is an artifact of three lucky data points. Right now that table has three rows in it and lives in a repository with two stars.
So the thing I would rather do than tell you what to conclude: if you run this on a model that is not in that table, post your two numbers somewhere I can find them. Especially if the model is small. The 1.3B row is the one that broke the rule, and one more small-model data point is worth more than ten more confirmations at 13B.
And if you own a 50-series card, go run the dispatch probe tonight. I would like to know how many people are paying for four-bit and receiving bf16.
Medium metadata
Suggested kicker: A converted checkpoint can load cleanly, dispatch natively, pass every structural check and still render a smear.
Primary sources:
- The three-build Wan 2.1 VACE comparison and threshold table: https://huggingface.co/JoaoZaokk/Wan2.1-VACE-1.3B-W4A4-ConvRot
- The measurement harness: https://github.com/JoaoZaokk/comfy-quant-bench
- Rotated NVFP4 methodology and the Blackwell fallback note: https://huggingface.co/pottokao/H3-RotNVFP4-ComfyUI-Loader
- The LoRA card documenting rotated-base failure: https://huggingface.co/KennethFal/vh5tape-vhs-lora-minimax-h3
- comfy-kitchen (the ConvRot kernels): https://github.com/Comfy-Org/comfy-kitchen
- Wan 2.1 VACE 1.3B base model: https://huggingface.co/Wan-AI/Wan2.1-VACE-1.3B