invoke-ai/InvokeAI · error · InvalidMatchError
PiD checkpoint has {len(unexpected)} keys PidNet does not ex
Error message
PiD checkpoint has {len(unexpected)} keys PidNet does not expect, which `load_pid_decoder` rejects too: {unexpected[:5]}{_and_more(unexpected)} What it means
The state dict contains keys PidNet does not define. `load_pid_decoder` would reject them with strict loading, so identification raises `InvalidMatchError` preemptively, listing the first 5 unexpected keys so installation and loading accept exactly the same set of files.
Source
Thrown at invokeai/backend/model_manager/configs/pid_decoder.py:163
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"
)
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 theView on GitHub (pinned to 0b6a024f2f)
Solutions
- Use the official released inference checkpoint from nvidia/PiD rather than a raw training dump
- Strip the extra keys (keeping only those matching the PidNet contract) if you must preprocess, then reinstall
- If the extra keys are v1.5 modules, see error on unsupported architecture — you need the legacy checkpoint
- Upgrade InvokeAI in case support for a newer layout was added
Example fix
// before: checkpoint contains net.lq_proj.* plus net.pit_inject.* (v1.5 modules)
// after: use the legacy release, or strip unexpected keys
sd = {k: v for k, v in torch.load(p).items() if k in required_keys} 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')
unexpected = pid_net_shapes(sd).keys() - required_pid_net_shapes().keys()
if unexpected:
raise SystemExit(f'Extra keys PidNet rejects: {sorted(unexpected, key=str)[:5]}') Type guard
def keys_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)
contract = required_pid_net_shapes()
return shapes.keys() == contract.keys() Try / catch
try:
install_model(path)
except InvalidMatchError as e:
if 'does not expect' in str(e):
logger.error('Checkpoint has extra keys (training dump or newer arch): %s', e)
else:
raise Prevention
- Use released inference checkpoints, not raw training dumps with optimizer state
- Match checkpoint version to the InvokeAI-supported legacy architecture
- Don't hand-edit/rename checkpoint keys
When it happens
Trigger: `_raise_if_pid_net_contract_unmet` in `from_model_on_disk` finds `shapes.keys() - contract.keys()` non-empty — extra tensors in the .pth (e.g. EMA wrappers, optimizer state, v1.5-only modules like PiT injection in an otherwise legacy file).
Common situations: Full training dumps (state_dict plus optimizer/scheduler entries) instead of the released inference checkpoint; new-architecture weights loaded by an older InvokeAI; renamed keys after manual surgery.
Related errors
- Unrecognized LLLite module name: '{name}'
- State dict appears to be in a legacy ControlNet-LLLite weigh
- State dict contains no LLLite modules (no 'lllite_dit_blocks
- LLLite module '{name}' is missing key '{down_key}'
- Unexpected key: {k}
AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29).
Data as JSON: /api/errors/c378f8524ec3b701.
Report an issue: GitHub.