invoke-ai/InvokeAI · warning · NotAMatchError

state dict does not look like a PiD decoder (no 'lq_proj.*'

Error message

state dict does not look like a PiD decoder (no 'lq_proj.*' keys)

What it means

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.

Source

Thrown at invokeai/backend/model_manager/configs/pid_decoder.py:287

    `PidNet` contract — the same keys and shapes `load_pid_decoder` demands — and the backbone then
    comes from the latent channel count in the weights, with an explicit override or the name as the
    tie-breaker for the architecturally identical FLUX.1 / SD3 / Qwen-Image family. `variant` is
    carried as data without participating in the discriminator tag (one config class per backbone).
    """

    type: Literal[ModelType.PiDDecoder] = Field(default=ModelType.PiDDecoder)
    format: Literal[ModelFormat.Checkpoint] = Field(default=ModelFormat.Checkpoint)

    @classmethod
    def from_model_on_disk(cls, mod: ModelOnDisk, override_fields: dict[str, Any]) -> Self:
        raise_if_not_file(mod)
        # An explicit `base` is validated against this class's Literal here, so it already narrows
        # identification to exactly one of the five PiD config classes.
        raise_for_override_fields(cls, override_fields)

        state_dict = mod.load_state_dict()
        if not _looks_like_pid_decoder(state_dict):
            raise NotAMatchError("state dict does not look like a PiD decoder (no 'lq_proj.*' keys)")

        # Imported lazily: it pulls in the vendored PiD network stack, which model identification has
        # no reason to load for the overwhelming majority of files.
        from invokeai.backend.pid.decode import required_pid_net_shapes

        contract = required_pid_net_shapes()
        shapes = pid_net_shapes(state_dict)

        # Everything from here to `_validate_base` is backbone-independent: each of these rejects a file
        # *every* PiD config class would reject for the same reason, which is exactly the case the plain
        # no-match signal cannot carry — no class matches, and the factory registers the file through its
        # `Unknown_Config` fallback. See `_raise_if_no_backbone_can_accept`.
        #
        # The latent projection carries both the architecture version and the backbone, so the checks
        # that read it can only speak when it is there. When it is not, the file is truncated, and the
        # contract check diagnoses that far better than a guess about the architecture would.
        if _LATENT_PROJ_KEY in shapes:
            _raise_if_discriminator_malformed(shapes, contract)

View on GitHub (pinned to 0b6a024f2f)

Solutions

  1. Verify you downloaded the PiD decoder weights (PiD_res2k*/... model_ema_bf16.pth), not the base PixDiT_T2I checkpoint
  2. Load the checkpoint and check `any('lq_proj' in k for k in sd)` to confirm it is a PiD decoder
  3. Let InvokeAI auto-identify the correct model type; do not force a PiD decoder registration for a non-PiD file
  4. Re-download if the file may be wrong/corrupted from the source repo

Example fix

// sanity check before installing
import torch
sd = torch.load('model_ema_bf16.pth', map_location='cpu')
assert any('lq_proj' in k for k in sd), 'not a PiD decoder'
Defensive patterns

Strategy: validation

Validate before calling

import torch
sd = torch.load(ckpt_path, map_location='cpu')
if not any(isinstance(k, str) and 'lq_proj' in k for k in sd):
    raise SystemExit('Not a PiD decoder (no lq_proj keys); check you downloaded the decoder, not base PixDiT weights.')

Type guard

def looks_like_pid_decoder(sd: dict) -> bool:
    return any(isinstance(k, str) and 'lq_proj' in k for k in sd)

Try / catch

try:
    install_model(path)
except NotAMatchError:
    logger.info('File is not a PiD decoder; letting other model configs identify it.')

Prevention

When it happens

Trigger: `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.

Common situations: 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.

Related errors


AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29). Data as JSON: /api/errors/2c530726c1d22f9d. Report an issue: GitHub.