invoke-ai/InvokeAI · error · ValueError
Unexpected keys loading {model_name}: {unexpected}
Error message
Unexpected keys loading {model_name}: {unexpected} What it means
After loading an SDNQ-quantized model, raise_on_incomplete_sdnq_load verifies no unexpected state_dict keys remain; leftovers indicate the checkpoint does not match the model architecture. Any unexpected keys raise ValueError naming the model and the offending keys.
Source
Thrown at invokeai/backend/quantization/sdnq/loaders.py:44
``load_state_dict`` with ``strict=False`` silently ignores the missing/unexpected key lists.
For SDNQ folder loads that is dangerous: a partial export, missing shard key or architecture
mismatch leaves required parameters on the meta device and returns a model that fails much later
during device movement or inference, far from the real cause. This raises with the offending
keys instead.
Args:
model_name: Human-readable name for the error message (e.g. "SDNQ Z-Image transformer").
missing_keys: The ``missing_keys`` returned by ``load_state_dict``.
unexpected_keys: The ``unexpected_keys`` returned by ``load_state_dict``.
allowed_missing: Keys that are expected to be absent (e.g. tied weights the caller re-shares
after load), which must not trigger a failure.
"""
allowed = set(allowed_missing)
real_missing = [k for k in missing_keys if k not in allowed]
unexpected = list(unexpected_keys)
if unexpected:
raise ValueError(f"Unexpected keys loading {model_name}: {unexpected}")
if real_missing:
raise ValueError(f"Missing keys loading {model_name} (required parameters left on meta): {real_missing}")
def _parse_quantization_config(config_path: Path) -> dict[str, Any]:
"""Parse quantization_config.json for SDNQ parameters."""
if not config_path.exists():
return {}
with open(config_path, "r", encoding="utf-8") as f:
return json.load(f)
_DTYPE_NAME_TO_QUANT_TYPE = {
"uint4": SDNQQuantizationType.UINT4_ASYM,
"int4": SDNQQuantizationType.UINT4_ASYM, # signed naming, same packed storage
"uint5": SDNQQuantizationType.INT5_ASYM,
"int5": SDNQQuantizationType.INT5_ASYM, # SDNQ dynamic-mixed uses this labelView on GitHub (pinned to 0b6a024f2f)
Solutions
- Load the checkpoint into the model architecture it was quantized from (match config and class)
- Re-export/re-quantize the model so keys match the current architecture
- Diff the reported unexpected keys against the model's state_dict to identify stale/extra tensors and remove or remap them
Example fix
// before model = _load_sdnq_transformer(folder_with_wrong_variant) // after model = _load_sdnq_transformer(folder_matching_config) # same arch as quantization_config.json
Defensive patterns
Strategy: validation
Validate before calling
model_keys = set(model.state_dict())
ckpt_keys = set(load_file(shard).keys() for shard in shards) # union across shards
extra = set().union(*ckpt_keys) - model_keys
assert not extra, f"checkpoint has keys not in model: {sorted(extra)[:5]}" Type guard
def is_compatible_checkpoint(ckpt_keys: set, model_keys: set) -> bool:
return ckpt_keys.issubset(model_keys) Try / catch
try:
model = _load_sdnq_transformer(path)
except ValueError as e:
logger.error(f"SDNQ checkpoint incompatible: {e}")
raise Prevention
- Verify quantization_config.json's architecture matches the model class being loaded
- Pin diffusers/transformers versions consistent with when the checkpoint was created
- Pre-check key sets against model.state_dict() before committing to the load
When it happens
Trigger: Loading an SDNQ checkpoint whose state_dict contains keys the target model class does not own — wrong architecture folder, renamed layers across versions, or extra quantization tensors the loader did not consume.
Common situations: Pointing the loader at a model variant different from the config (e.g. a different transformer revision); loading a checkpoint saved from a modified model; upstream diffusers key renames after a version bump.
Related errors
- Invalid or expired token
- missing keys after fp8 load: {missing[:10]}
- state dict does not look like bnb quantized nf4
- state dict does not look like GGUF quantized
- state dict looks like GGUF quantized
AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29).
Data as JSON: /api/errors/2fb6bd2c6ea27910.
Report an issue: GitHub.