Skip to content

model_patcher: skip synthetic quant keys in get_key_patches#14413

Open
liminfei-amd wants to merge 1 commit into
Comfy-Org:masterfrom
liminfei-amd:amd-rocm/14382-quant-merge-keys
Open

model_patcher: skip synthetic quant keys in get_key_patches#14413
liminfei-amd wants to merge 1 commit into
Comfy-Org:masterfrom
liminfei-amd:amd-rocm/14382-quant-merge-keys

Conversation

@liminfei-amd

@liminfei-amd liminfei-amd commented Jun 11, 2026

Copy link
Copy Markdown

Summary

ModelMergeSimple — and every get_key_patches-based merge/save node — crashes with
AttributeError: 'Linear' object has no attribute 'weight_scale' when the model being merged is a
quantized (fp8 / QuantizedTensor) checkpoint. 100% reproducible, no sampling/GPU needed.

Problem

A QuantizedTensor flattens into synthetic state_dict keys*.weight plus *.weight_scale /
*.weight_scale_2 / *.input_scale and a comfy_quant marker (per core comfy/quant_ops.py QUANT_ALGOS).
get_key_patches() iterates model_state_dict() and calls get_key_weight(), which does
getattr(op, op_keys[1]). For the synthetic sub-keys that is getattr(linear, "weight_scale") — not a
module attribute (the scale lives inside the QuantizedTensor in .weight), so it throws.

Change

Skip the synthetic quant sub-keys in get_key_patches(). The suffix set is gathered from core
comfy.quant_ops.QUANT_ALGOS (so new quant types are covered automatically), plus the comfy_quant
marker. The real *.weight key keeps its existing convert_weight dequant path, so quantized merging
still works as designed.

This skips only the known, core-generated quant suffixes — not a blanket getattr(op, key, None)
swallow, which would also hide a genuinely missing weight (cf. the #11585 discussion about not masking
bugs).

Validation

A standalone harness models a quantized state_dict (*.weight + *.weight_scale + *.input_scale +
comfy_quant): the stock path raises AttributeError: 'Linear' object has no attribute 'weight_scale',
and with the fix get_key_patches returns only the real *.weight key (preserving the dequant path) with
no crash. python -m py_compile comfy/model_patcher.py is clean. The fix is pure Python and
hardware-independent.

Fixes #14382


AI usage disclosure: this change was prepared with AI assistance; a human reviewed and verified it and can explain every line. (Reviewed by AMD engineers before submission.)

get_key_patches() iterates model_state_dict() and calls get_key_weight(),
which does getattr(op, op_keys[1]). A quantized (fp8/QuantizedTensor)
checkpoint flattens into synthetic state_dict keys (*.weight_scale,
*.weight_scale_2, *.input_scale and a comfy_quant marker) that are
components of the QuantizedTensor in *.weight, not module attributes, so
getattr(linear, "weight_scale") raises AttributeError and every merge node
(ModelMergeSimple, ModelMergeBlocks, CLIPMergeSimple, ...) crashes on a
quantized model2.

Skip the synthetic quant sub-keys, gathered from comfy.quant_ops.QUANT_ALGOS
so new quant types are covered automatically. The real *.weight key keeps
its convert_weight dequant path, so quantized merging still works. Only the
known core-defined suffixes are skipped (not a blanket getattr swallow that
would also hide a genuinely missing weight).

Fixes Comfy-Org#14382

Signed-off-by: liminfei-amd <91481003+liminfei-amd@users.noreply.github.com>
@liminfei-amd liminfei-amd force-pushed the amd-rocm/14382-quant-merge-keys branch from 06ddebf to 8d53b96 Compare June 11, 2026 04:28
@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR extends ModelPatcher to filter quantization synthetic state_dict keys. It introduces a helper function to collect synthetic key suffixes (such as weight_scale, input_scale) by inspecting comfy.quant_ops.QUANT_ALGOS, stores these in a module-level constant, and updates ModelPatcher.get_key_patches() to skip keys matching these synthetic suffixes. This prevents non-module attributes of QuantizedTensor objects from being processed as patchable weights.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: skipping synthetic quantization keys in get_key_patches to prevent AttributeError crashes.
Linked Issues check ✅ Passed The code change fully addresses issue #14382: prevents AttributeError by skipping synthetic quant keys, preserves dequantization path for real weights, and limits fix to known core-generated suffixes.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing the quantized model merging crash: adding _collect_quant_synthetic_keys() and _QUANT_SYNTHETIC_KEYS constant, and updating get_key_patches() to skip synthetic keys.
Description check ✅ Passed The PR description clearly documents the bug, the root cause involving QuantizedTensor synthetic keys, the solution implemented, and validation steps performed.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant