{"record":{"id":"2c530726c1d22f9d","repo":"invoke-ai/InvokeAI","slug":"state-dict-does-not-look-like-a-pid-decoder-no-l","errorCode":null,"errorMessage":"state dict does not look like a PiD decoder (no 'lq_proj.*' keys)","messagePattern":"state dict does not look like a PiD decoder \\(no 'lq_proj\\.\\*' keys\\)","errorType":"exception","errorClass":"NotAMatchError","httpStatus":null,"severity":"warning","filePath":"invokeai/backend/model_manager/configs/pid_decoder.py","lineNumber":287,"sourceCode":"    `PidNet` contract — the same keys and shapes `load_pid_decoder` demands — and the backbone then\n    comes from the latent channel count in the weights, with an explicit override or the name as the\n    tie-breaker for the architecturally identical FLUX.1 / SD3 / Qwen-Image family. `variant` is\n    carried as data without participating in the discriminator tag (one config class per backbone).\n    \"\"\"\n\n    type: Literal[ModelType.PiDDecoder] = Field(default=ModelType.PiDDecoder)\n    format: Literal[ModelFormat.Checkpoint] = Field(default=ModelFormat.Checkpoint)\n\n    @classmethod\n    def from_model_on_disk(cls, mod: ModelOnDisk, override_fields: dict[str, Any]) -> Self:\n        raise_if_not_file(mod)\n        # An explicit `base` is validated against this class's Literal here, so it already narrows\n        # identification to exactly one of the five PiD config classes.\n        raise_for_override_fields(cls, override_fields)\n\n        state_dict = mod.load_state_dict()\n        if not _looks_like_pid_decoder(state_dict):\n            raise NotAMatchError(\"state dict does not look like a PiD decoder (no 'lq_proj.*' keys)\")\n\n        # Imported lazily: it pulls in the vendored PiD network stack, which model identification has\n        # no reason to load for the overwhelming majority of files.\n        from invokeai.backend.pid.decode import required_pid_net_shapes\n\n        contract = required_pid_net_shapes()\n        shapes = pid_net_shapes(state_dict)\n\n        # Everything from here to `_validate_base` is backbone-independent: each of these rejects a file\n        # *every* PiD config class would reject for the same reason, which is exactly the case the plain\n        # no-match signal cannot carry — no class matches, and the factory registers the file through its\n        # `Unknown_Config` fallback. See `_raise_if_no_backbone_can_accept`.\n        #\n        # The latent projection carries both the architecture version and the backbone, so the checks\n        # that read it can only speak when it is there. When it is not, the file is truncated, and the\n        # contract check diagnoses that far better than a guess about the architecture would.\n        if _LATENT_PROJ_KEY in shapes:\n            _raise_if_discriminator_malformed(shapes, contract)","sourceCodeStart":269,"sourceCodeEnd":305,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/backend/model_manager/configs/pid_decoder.py#L269-L305","documentation":"This is the identification gate: a state dict must contain a key containing `lq_proj` (the diagnostic marker of PidDistillModel's `net.lq_proj...` weights) for the file to be considered a PiD decoder at all. If no such key exists, `NotAMatchError` is raised — a normal 'not this model type' signal, letting the factory try other config classes.","triggerScenarios":"`from_model_on_disk` calls `_looks_like_pid_decoder(state_dict)` and finds no key with the `lq_proj` substring — e.g. installing a base PixDiT_T2I checkpoint, a VAE, or any non-PiD .pth that the router still offered to the PiD config classes.","commonSituations":"Installing the wrong artifact from the nvidia/PiD repo (base PixDiT weights have no lq_proj); pointing the installer at an unrelated diffusion model checkpoint; single-file install where the router mislabels the model.","solutions":["Verify you downloaded the PiD decoder weights (PiD_res2k*/... model_ema_bf16.pth), not the base PixDiT_T2I checkpoint","Load the checkpoint and check `any('lq_proj' in k for k in sd)` to confirm it is a PiD decoder","Let InvokeAI auto-identify the correct model type; do not force a PiD decoder registration for a non-PiD file","Re-download if the file may be wrong/corrupted from the source repo"],"exampleFix":"// sanity check before installing\nimport torch\nsd = torch.load('model_ema_bf16.pth', map_location='cpu')\nassert any('lq_proj' in k for k in sd), 'not a PiD decoder'","handlingStrategy":"validation","validationCode":"import torch\nsd = torch.load(ckpt_path, map_location='cpu')\nif not any(isinstance(k, str) and 'lq_proj' in k for k in sd):\n    raise SystemExit('Not a PiD decoder (no lq_proj keys); check you downloaded the decoder, not base PixDiT weights.')","typeGuard":"def looks_like_pid_decoder(sd: dict) -> bool:\n    return any(isinstance(k, str) and 'lq_proj' in k for k in sd)","tryCatchPattern":"try:\n    install_model(path)\nexcept NotAMatchError:\n    logger.info('File is not a PiD decoder; letting other model configs identify it.')","preventionTips":["Download the PiD_res2k*/... decoder .pth, not the base PixDiT_T2I checkpoint","Sanity-check keys with `any('lq_proj' in k for k in sd)` before installing","Let auto-identification pick the model type instead of forcing PiD"],"tags":["checkpoint","model-identification","wrong-model-type"],"backgroundTag":"model-not-a-match","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}