invoke-ai/InvokeAI · error · InvalidMatchError

PiD checkpoint has {len(mismatched)} weights whose shape Pid

Error message

PiD checkpoint has {len(mismatched)} weights whose shape PidNet cannot accept (e.g. {k}: {got}, expected {want}); loading it would fail with a size mismatch

What it means

Beyond key presence, each weight's shape is compared to the contract; `lq_proj.latent_proj.0.weight` is excluded because its shape legitimately varies by backbone (it has its own dedicated checks). Any other mismatch means `load_pid_decoder` would fail with a torch size-mismatch error, so identification raises `InvalidMatchError` naming an example key, its got shape, and the expected shape.

Source

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

    # 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"
        )


def _name_components(mod: ModelOnDisk, override_fields: dict[str, Any]) -> tuple[str, ...]:
    """The name evidence for backbone and variant, most specific first.

    NVIDIA distributes PiD checkpoints as
    ``PiD_res2k_sr4x_official_<backbone>_distill_4step/model_ema_bf16.pth``, so the backbone and the
    preset usually live in the *directory* name rather than the weights filename. A direct
    single-file install stores the checkpoint as ``<uuid>/model_ema_bf16.pth`` and drops that
    directory, which is why the install source is consulted at all: for an HF or URL install it still
    carries NVIDIA's name.

    These used to be concatenated into one string and substring-matched, which let a fixed backbone
    precedence decide cases the name had already answered — `/flux/model_sd3.pth` matched `flux`
    first and was registered as FLUX although the file itself says sd3. Matching component by

View on GitHub (pinned to 0b6a024f2f)

Solutions

  1. Obtain the unmodified official checkpoint matching InvokeAI's `build_pid_net` legacy configuration
  2. If it's a fine-tune with different dims, it is incompatible — request support or use the original architecture
  3. Re-download; compare the reported example shape against the official file to confirm corruption vs intentional change
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')
contract = required_pid_net_shapes(); shapes = pid_net_shapes(sd)
bad = [(k, shapes[k], w) for k, w in contract.items()
       if k != 'lq_proj.latent_proj.0.weight' and shapes[k] != w]
if bad:
    raise SystemExit(f'Shape mismatches, e.g. {bad[0]}')

Type guard

def shapes_match_pid_net(sd: dict) -> bool:
    from invokeai.backend.pid.decode import required_pid_net_shapes
    from invokeai.backend.pid.state_dict_utils import pid_net_shapes
    shapes = pid_net_shapes(sd)
    return all(shapes[k] == w for k, w in required_pid_net_shapes().items()
               if k != 'lq_proj.latent_proj.0.weight')

Try / catch

try:
    install_model(path)
except InvalidMatchError as e:
    if 'whose shape PidNet cannot accept' in str(e):
        logger.error('Incompatible/fine-tuned PidNet dims: %s', e)
    else:
        raise

Prevention

When it happens

Trigger: `_raise_if_pid_net_contract_unmet` in `from_model_on_disk` finds contract keys present with wrong shapes — e.g. a decoder trained with modified PidNet hyperparameters, or a spliced checkpoint mixing tensors from different releases.

Common situations: Third-party fine-tunes of PidNet with changed dims; checkpoints converted between formats incorrectly; mixing weights from different PiD releases into one file.

Related errors


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