invoke-ai/InvokeAI · critical · ValueError

Missing keys loading {model_name} (required parameters left

Error message

Missing keys loading {model_name} (required parameters left on meta): {real_missing}

What it means

Companion to the unexpected-keys check: after SDNQ load, keys still reported missing (excluding explicitly allowed_missing) mean required parameters were never materialized and remain on the meta device — the model would fail or silently produce garbage at inference. ValueError lists the unmet keys.

Source

Thrown at invokeai/backend/quantization/sdnq/loaders.py:46

    For SDNQ folder loads that is dangerous: a partial export, missing shard key or architecture
    mismatch leaves required parameters on the meta device and returns a model that fails much later
    during device movement or inference, far from the real cause. This raises with the offending
    keys instead.

    Args:
        model_name: Human-readable name for the error message (e.g. "SDNQ Z-Image transformer").
        missing_keys: The ``missing_keys`` returned by ``load_state_dict``.
        unexpected_keys: The ``unexpected_keys`` returned by ``load_state_dict``.
        allowed_missing: Keys that are expected to be absent (e.g. tied weights the caller re-shares
            after load), which must not trigger a failure.
    """
    allowed = set(allowed_missing)
    real_missing = [k for k in missing_keys if k not in allowed]
    unexpected = list(unexpected_keys)
    if unexpected:
        raise ValueError(f"Unexpected keys loading {model_name}: {unexpected}")
    if real_missing:
        raise ValueError(f"Missing keys loading {model_name} (required parameters left on meta): {real_missing}")


def _parse_quantization_config(config_path: Path) -> dict[str, Any]:
    """Parse quantization_config.json for SDNQ parameters."""
    if not config_path.exists():
        return {}

    with open(config_path, "r", encoding="utf-8") as f:
        return json.load(f)


_DTYPE_NAME_TO_QUANT_TYPE = {
    "uint4": SDNQQuantizationType.UINT4_ASYM,
    "int4": SDNQQuantizationType.UINT4_ASYM,  # signed naming, same packed storage
    "uint5": SDNQQuantizationType.INT5_ASYM,
    "int5": SDNQQuantizationType.INT5_ASYM,  # SDNQ dynamic-mixed uses this label
    "int8": SDNQQuantizationType.INT8_SYM,
    "uint8": SDNQQuantizationType.UINT8_SYM,

View on GitHub (pinned to 0b6a024f2f)

Solutions

  1. Re-download the full model files (check shard count/sizes against the repo manifest)
  2. Re-quantize the model so all required parameters are present
  3. If specific keys are legitimately absent (e.g. optional buffers), pass them via allowed_missing

Example fix

// before
raise_on_incomplete_sdnq_load(missing_keys, unexpected, model_name)
// after
raise_on_incomplete_sdnq_load(missing_keys, unexpected, model_name, allowed_missing=["rotary_emb.inv_freq"])
Defensive patterns

Strategy: validation

Validate before calling

expected = model.state_dict().keys()
loaded = set().union(*(load_file(f).keys() for f in shards))
missing = set(expected) - loaded
assert not missing, f"checkpoint incomplete, missing: {sorted(missing)[:5]}"

Type guard

def checkpoint_is_complete(loaded_keys: set, model_keys) -> bool:
    return set(model_keys).issubset(loaded_keys)

Try / catch

try:
    model = _load_sdnq_vae(path)
except ValueError as e:
    logger.critical(f"Model files incomplete — re-download: {e}")
    raise

Prevention

When it happens

Trigger: Calling any SDNQ load path (_load_sdnq_transformer, _load_sdnq_vae, _load_sdnq_t5, etc.) where the safetensors files omit tensors the model requires and those keys are not in allowed_missing.

Common situations: Truncated or partially downloaded shard files; a checkpoint quantized from an older architecture missing newly added layers; corrupted bundle where some tensors were dropped at quantization time.

Related errors


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