invoke-ai/InvokeAI · error · RuntimeError

PiD checkpoint has {len(not_strings)} keys that are not stri

Error message

PiD checkpoint has {len(not_strings)} keys that are not strings and so cannot name a PidNet parameter: {not_strings[:5]}(+ {len(not_strings) - 5} more)

What it means

Before handing the state dict to torch, load_pid_decoder checks that every checkpoint key is a string, because nn.Module.load_state_dict would otherwise crash with an opaque AttributeError inside .startswith(). Non-string keys mean the .pth file unpickled to something malformed (e.g. a dict keyed by ints/objects), so it is rejected up front with a RuntimeError showing up to 5 offending keys. This makes a corrupt checkpoint fail with the same readable message style as other unusable checkpoints.

Source

Thrown at invokeai/backend/pid/decode.py:265


def load_pid_decoder(state_dict: dict[Any, Tensor], backbone: BaseModelType) -> PidNet:
    """Instantiate a PidNet for *backbone* and populate it with *state_dict*.

    The state dict is expected to be the model-manager loader's output, i.e.
    already stripped of the `net.` prefix used by NVIDIA's distill model
    serialisation. The caller still owns dtype/device placement of the
    returned net.
    """
    net = build_pid_net(backbone)

    # A `.pth` unpickles to whatever it contains, and a bare (un-prefixed) checkpoint reaches here
    # with its keys untouched — see `strip_net_prefix`. `nn.Module.load_state_dict` calls
    # `.startswith()` on every key, so a non-string one raises AttributeError from inside torch
    # before any of the reporting below runs. Reject it here instead, so a malformed checkpoint gets
    # the same kind of message as every other unusable one.
    if not_strings := sorted((k for k in state_dict if not isinstance(k, str)), key=str):
        raise RuntimeError(
            f"PiD checkpoint has {len(not_strings)} keys that are not strings and so cannot name a "
            f"PidNet parameter: {not_strings[:5]}"
            + (f" (+ {len(not_strings) - 5} more)" if len(not_strings) > 5 else "")
        )

    # strict=False so we can report missing and unexpected keys separately; both are fatal. The model
    # cache builds loaders under `skip_torch_weight_init()`, which no-ops every `reset_parameters()`,
    # so a key the checkpoint does not supply is left as uninitialised memory rather than a sane
    # default — a partial checkpoint would decode to garbage / NaNs instead of failing.
    missing, unexpected = net.load_state_dict(state_dict, strict=False)
    if unexpected:
        raise RuntimeError(
            f"PiD checkpoint has unexpected keys not present in PidNet: {unexpected[:5]}"
            + (f" (+ {len(unexpected) - 5} more)" if len(unexpected) > 5 else "")
        )
    if missing:
        lq = [k for k in missing if k.startswith("lq_proj.")]
        detail = (

View on GitHub (pinned to 0b6a024f2f)

Solutions

  1. Verify the file is a genuine PyTorch state dict (torch.load and inspect type(key) for key in sd)
  2. Re-export/re-save the checkpoint with torch.save(model.state_dict(), path)
  3. Ensure load_pid_decoder is pointed at the intended .pth file
Defensive patterns

Strategy: validation

Validate before calling

sd = torch.load(path, map_location="cpu")
bad = [k for k in sd if not isinstance(k, str)]
assert not bad, f"non-string keys: {bad[:5]}"

Type guard

def is_valid_state_dict(sd) -> bool:
    return isinstance(sd, dict) and all(isinstance(k, str) for k in sd)

Try / catch

try:
    net = load_pid_decoder(path, backbone=backbone)
except RuntimeError as e:
    if "not strings" in str(e):
        logger.error(f"Malformed checkpoint {path}: {e}")
    raise

Prevention

When it happens

Trigger: Loading a PiD decoder checkpoint whose top-level state-dict keys are not all strings — e.g. a pickled dict with integer/None/object keys, or a non-state-dict object that happens to be dict-like.

Common situations: Corrupted or hand-crafted .pth files, checkpoints saved from non-PyTorch serialization, or loading the wrong file entirely (a pickled dataset/dict instead of a model).

Related errors


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