invoke-ai/InvokeAI · error · RuntimeError

Encountered unexpected IP Adapter state dict key: '{key}'.

Error message

Encountered unexpected IP Adapter state dict key: '{key}'.

What it means

When loading an IP-Adapter checkpoint, InvokeAI buckets every tensor key into one of three sub-dicts (image_proj_model, image_proj, adapter_modules) based on key prefixes. If a key in the loaded state dict starts with none of those prefixes, the checkpoint does not match any known IP-Adapter layout, so load_ip_adapter_tensors refuses to silently drop data and raises this RuntimeError.

Source

Thrown at invokeai/backend/ip_adapter/ip_adapter.py:229

        "ip_adapter": {},
        "image_proj": {},
        "adapter_modules": {},  # added for noobai-mark-ipa
        "image_proj_model": {},  # added for noobai-mark-ipa
    }

    if ip_adapter_ckpt_path.suffix == ".safetensors":
        model = safetensors.torch.load_file(ip_adapter_ckpt_path, device=device)
        for key in model.keys():
            if key.startswith("ip_adapter."):
                state_dict["ip_adapter"][key.replace("ip_adapter.", "")] = model[key]
            elif key.startswith("image_proj_model."):
                state_dict["image_proj_model"][key.replace("image_proj_model.", "")] = model[key]
            elif key.startswith("image_proj."):
                state_dict["image_proj"][key.replace("image_proj.", "")] = model[key]
            elif key.startswith("adapter_modules."):
                state_dict["adapter_modules"][key.replace("adapter_modules.", "")] = model[key]
            else:
                raise RuntimeError(f"Encountered unexpected IP Adapter state dict key: '{key}'.")
    else:
        ip_adapter_diffusers_checkpoint_path = ip_adapter_ckpt_path / "ip_adapter.bin"
        state_dict = torch.load(ip_adapter_diffusers_checkpoint_path, map_location="cpu")

    return state_dict


def build_ip_adapter(
    ip_adapter_ckpt_path: pathlib.Path, device: torch.device, dtype: torch.dtype = torch.float16
) -> Union[IPAdapter, IPAdapterPlus, IPAdapterPlusXL, IPAdapterPlus]:
    state_dict = load_ip_adapter_tensors(ip_adapter_ckpt_path, device.type)

    # IPAdapter (with ImageProjModel)
    if "proj.weight" in state_dict["image_proj"]:
        return IPAdapter(state_dict, device=device, dtype=dtype)

    # IPAdaterPlus or IPAdapterPlusXL (with Resampler)
    elif "proj_in.weight" in state_dict["image_proj"]:

View on GitHub (pinned to 0b6a024f2f)

Solutions

  1. Verify the checkpoint is an official IP-Adapter file (h94/IP-Adapter) and re-download it
  2. Open the file with torch.load / safetensors and inspect its keys to confirm they start with image_proj_model., image_proj., or adapter_modules.
  3. Upgrade InvokeAI — newer versions recognize more IP-Adapter checkpoint formats.
  4. If the file contains unrelated extra keys, strip them (re-save only the recognized tensors) rather than patching the loader.

Example fix

// before
ip_adapter = Path('/models/ip_adapter/custom_faceid.bin')  # unknown key layout
// after
ip_adapter = Path('/models/ip_adapter/ip-adapter-plus_sd15.bin')  # official layout
Defensive patterns

Strategy: validation

Validate before calling

import torch
sd = torch.load(path, map_location='cpu')
valid = ('image_proj_model.', 'image_proj.', 'adapter_modules.')
bad = [k for k in sd.keys() if not k.startswith(valid)]
if bad:
    raise ValueError(f'Unrecognized IP-Adapter keys: {bad[:5]}')

Type guard

def is_ip_adapter_state_dict(sd) -> bool:
    prefixes = ('image_proj_model.', 'image_proj.', 'adapter_modules.')
    return all(k.startswith(prefixes) for k in sd.keys())

Try / catch

try:
    ip_adapter = build_ip_adapter(ckpt_path, device, dtype)
except RuntimeError as e:
    if 'unexpected IP Adapter state dict key' in str(e):
        logger.error('Checkpoint is not a supported IP-Adapter layout: %s', ckpt_path)
        ip_adapter = None
    else:
        raise

Prevention

When it happens

Trigger: Calling build_ip_adapter (via _load_model) with an IP-Adapter checkpoint file whose state dict contains keys outside the recognized prefixes — e.g. a corrupted/custom/resaved checkpoint, a different adapter family (IP-Adapter-FaceID, ControlNet-adjacent weights), or a file with extra keys like 'lora' or metadata tensors.

Common situations: Users point InvokeAI at an IP-Adapter .bin/.safetensors downloaded from a non-standard repo, hand-edited or converted checkpoints, or newer adapter formats released after this InvokeAI version was published.

Related errors


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