invoke-ai/InvokeAI · error · InvalidMatchError

PiD checkpoint is missing {len(missing)} of the weights requ

Error message

PiD checkpoint is missing {len(missing)} of the weights required by PidNet; the file is incomplete and cannot be used as a PiD decoder: {missing[:5]}{_and_more(missing)}

What it means

The checkpoint is compared against the exact key set `required_pid_net_shapes()` demands (mirroring `load_pid_decoder`). If contract keys are absent from the state dict, the file is incomplete and would leave weights uninitialized (loaders run under `skip_torch_weight_init`), so an `InvalidMatchError` lists the first 5 missing keys.

Source

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

    Missing *and* unexpected keys are fatal here because both are fatal there, which is what makes
    installation and loading accept the same set of files. A stricter installer cannot reject a file
    that would have loaded: the loader already refuses everything rejected here.

    `_LATENT_PROJ_KEY` is excluded from the shape comparison, and only from that: it is the one
    parameter whose shape legitimately varies by backbone, and its variable dimensions each have a
    dedicated check above with a dedicated message.
    """
    # No "this is a base PixDiT_T2I checkpoint" special case, unlike `load_pid_decoder`: those weights
    # carry no `lq_proj` key at all, so such a file never reaches here — `_looks_like_pid_decoder`
    # has already turned it away, and with a better message.
    # Both sorts take `key=str`: a bare checkpoint's keys need not all be strings (see
    # `strip_net_prefix`), and sorting a mixed set raises TypeError — which the factory answers with
    # the `Unknown_Config` registration these checks exist to prevent, so the crash fails as a silent
    # accept rather than loudly. Only `unexpected` can hold one today; sorting both the same way keeps
    # that from depending on which set is on which side of the subtraction.
    if missing := sorted(contract.keys() - shapes.keys(), key=str):
        raise InvalidMatchError(
            f"PiD checkpoint is missing {len(missing)} of the weights required by PidNet; the file is "
            f"incomplete and cannot be used as a PiD decoder: {missing[:5]}{_and_more(missing)}"
        )

    if unexpected := sorted(shapes.keys() - contract.keys(), key=str):
        raise InvalidMatchError(
            f"PiD checkpoint has {len(unexpected)} keys PidNet does not expect, which `load_pid_decoder` "
            f"rejects too: {unexpected[:5]}{_and_more(unexpected)}"
        )

    mismatched = [(k, shapes[k], want) for k, want in contract.items() if k != _LATENT_PROJ_KEY and shapes[k] != want]
    if mismatched:
        k, got, want = mismatched[0]
        raise InvalidMatchError(
            f"PiD checkpoint has {len(mismatched)} weights whose shape PidNet cannot accept "
            f"(e.g. {k}: {got}, expected {want}); loading it would fail with a size mismatch"
        )

View on GitHub (pinned to 0b6a024f2f)

Solutions

  1. Re-download the checkpoint and verify file size/checksum against the source
  2. Install the complete model (all shards) from the original repo rather than copying individual files
  3. Delete the broken file and reinstall via InvokeAI's model manager so integrity is handled for you

Example fix

# before: manually copied partial checkpoint
$ cp model_ema_bf16.pth $INVOKEAI_ROOT/models/...   # incomplete
// after: verify and re-download
$ huggingface-cli download nvidia/PiD <path> --local-dir ...
$ sha256sum -c expected_checksums.txt
Defensive patterns

Strategy: validation

Validate before calling

from invokeai.backend.pid.decode import required_pid_net_shapes
from invokeai.backend.pid.state_dict_utils import pid_net_shapes
import torch
sd = torch.load(ckpt_path, map_location='cpu')
missing = required_pid_net_shapes().keys() - pid_net_shapes(sd).keys()
if missing:
    raise SystemExit(f'Incomplete PiD checkpoint, missing {len(missing)} weights, e.g. {sorted(missing, key=str)[:5]}')

Type guard

def is_complete_pid_decoder(sd: dict) -> bool:
    from invokeai.backend.pid.decode import required_pid_net_shapes
    from invokeai.backend.pid.state_dict_utils import pid_net_shapes
    return not (required_pid_net_shapes().keys() - pid_net_shapes(sd).keys())

Try / catch

try:
    install_model(path)
except InvalidMatchError as e:
    if 'is missing' in str(e) and 'PidNet' in str(e):
        logger.error('Truncated/incomplete checkpoint, re-download: %s', e)
    else:
        raise

Prevention

When it happens

Trigger: `_raise_if_pid_net_contract_unmet` in `from_model_on_disk` finds `contract.keys() - shapes.keys()` non-empty — e.g. a file carrying only LQ weights but none of the 385 backbone weights, or a truncated download.

Common situations: Partially downloaded .pth from HuggingFace; manually assembled/stripped checkpoints; single-file install that lost part of a sharded set.

Related errors


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