{"record":{"id":"2fb6bd2c6ea27910","repo":"invoke-ai/InvokeAI","slug":"unexpected-keys-loading-model-name-unexpected","errorCode":null,"errorMessage":"Unexpected keys loading {model_name}: {unexpected}","messagePattern":"Unexpected keys loading (.+?): (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"invokeai/backend/quantization/sdnq/loaders.py","lineNumber":44,"sourceCode":"\n    ``load_state_dict`` with ``strict=False`` silently ignores the missing/unexpected key lists.\n    For SDNQ folder loads that is dangerous: a partial export, missing shard key or architecture\n    mismatch leaves required parameters on the meta device and returns a model that fails much later\n    during device movement or inference, far from the real cause. This raises with the offending\n    keys instead.\n\n    Args:\n        model_name: Human-readable name for the error message (e.g. \"SDNQ Z-Image transformer\").\n        missing_keys: The ``missing_keys`` returned by ``load_state_dict``.\n        unexpected_keys: The ``unexpected_keys`` returned by ``load_state_dict``.\n        allowed_missing: Keys that are expected to be absent (e.g. tied weights the caller re-shares\n            after load), which must not trigger a failure.\n    \"\"\"\n    allowed = set(allowed_missing)\n    real_missing = [k for k in missing_keys if k not in allowed]\n    unexpected = list(unexpected_keys)\n    if unexpected:\n        raise ValueError(f\"Unexpected keys loading {model_name}: {unexpected}\")\n    if real_missing:\n        raise ValueError(f\"Missing keys loading {model_name} (required parameters left on meta): {real_missing}\")\n\n\ndef _parse_quantization_config(config_path: Path) -> dict[str, Any]:\n    \"\"\"Parse quantization_config.json for SDNQ parameters.\"\"\"\n    if not config_path.exists():\n        return {}\n\n    with open(config_path, \"r\", encoding=\"utf-8\") as f:\n        return json.load(f)\n\n\n_DTYPE_NAME_TO_QUANT_TYPE = {\n    \"uint4\": SDNQQuantizationType.UINT4_ASYM,\n    \"int4\": SDNQQuantizationType.UINT4_ASYM,  # signed naming, same packed storage\n    \"uint5\": SDNQQuantizationType.INT5_ASYM,\n    \"int5\": SDNQQuantizationType.INT5_ASYM,  # SDNQ dynamic-mixed uses this label","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/backend/quantization/sdnq/loaders.py#L26-L62","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nmodel = _load_sdnq_transformer(folder_with_wrong_variant)\n// after\nmodel = _load_sdnq_transformer(folder_matching_config)  # same arch as quantization_config.json","handlingStrategy":"validation","validationCode":"model_keys = set(model.state_dict())\nckpt_keys = set(load_file(shard).keys() for shard in shards)  # union across shards\nextra = set().union(*ckpt_keys) - model_keys\nassert not extra, f\"checkpoint has keys not in model: {sorted(extra)[:5]}\"","typeGuard":"def is_compatible_checkpoint(ckpt_keys: set, model_keys: set) -> bool:\n    return ckpt_keys.issubset(model_keys)","tryCatchPattern":"try:\n    model = _load_sdnq_transformer(path)\nexcept ValueError as e:\n    logger.error(f\"SDNQ checkpoint incompatible: {e}\")\n    raise","preventionTips":["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"],"tags":["valueerror","state-dict","model-loading","quantization"],"backgroundTag":"state-dict-key-mismatch","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}