{"record":{"id":"db56f6e7d1313fa6","repo":"invoke-ai/InvokeAI","slug":"unexpected-keys-loading-ideogram-4-text-encoder","errorCode":null,"errorMessage":"unexpected keys loading Ideogram 4 text encoder: {unexpected[:10]}","messagePattern":"unexpected keys loading Ideogram 4 text encoder: (.+?)","errorType":"validation","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"invokeai/backend/model_manager/load/model_loaders/ideogram4.py","lineNumber":208,"sourceCode":"                swap_linears_to_fp8(model, sd, compute_dtype=compute_dtype)\n            load_fp8_state_dict(model, sd, device=torch.device(\"cpu\"), dtype=compute_dtype, assign=True, strict=False)\n            _verify_encoder_fully_materialized(model, context=\"Ideogram 4 fp8 text encoder\")\n            model.eval()\n            return model\n\n        is_bnb_nf4 = \"quantization_config\" in raw_cfg and bool(raw_cfg[\"quantization_config\"].get(\"load_in_4bit\"))\n\n        with accelerate.init_empty_weights():\n            model = AutoModel.from_config(cfg)\n            if is_bnb_nf4:\n                model = quantize_model_nf4(model, modules_to_not_convert=set(), compute_dtype=compute_dtype)\n\n        _, unexpected = model.load_state_dict(sd, strict=False, assign=True)\n        # Unexpected keys signal a wrong or contaminated checkpoint and must hard-fail. Missing keys are\n        # acceptable only for tied weights (resolved by _verify_encoder_fully_materialized via\n        # tie_weights); any genuinely missing non-tied weight is caught there as a leftover meta tensor.\n        if unexpected:\n            raise RuntimeError(f\"unexpected keys loading Ideogram 4 text encoder: {unexpected[:10]}\")\n        _verify_encoder_fully_materialized(model, context=\"Ideogram 4 text encoder\")\n        if not is_bnb_nf4:\n            model = model.to(compute_dtype)\n        model.eval()\n        return model\n\n    def _load_vae(self, model_path: Path) -> AnyModel:\n        from invokeai.backend.ideogram4.autoencoder import (\n            AutoEncoder,\n            AutoEncoderParams,\n            convert_diffusers_state_dict,\n        )\n\n        target_device = TorchDevice.choose_torch_device()\n        model_dtype = TorchDevice.choose_bfloat16_safe_dtype(target_device)\n\n        sd = load_file(model_path / \"vae\" / \"diffusion_pytorch_model.safetensors\")\n        sd = convert_diffusers_state_dict(sd)","sourceCodeStart":190,"sourceCodeEnd":226,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/backend/model_manager/load/model_loaders/ideogram4.py#L190-L226","documentation":"The Ideogram 4 text encoder loads its state dict with strict=False (so tied-weight omissions don't fail), but unexpected keys indicate the checkpoint contains tensors that do not exist in the model — evidence of a wrong or contaminated checkpoint. Because these cannot be resolved by tying or verification, the loader hard-fails immediately with the first 10 unexpected key names.","triggerScenarios":"In _load_text_encoder, model.load_state_dict(sd, strict=False, assign=True) returns a non-empty `unexpected` list — the checkpoint has keys that don't match the text-encoder architecture (wrong variant, extra modules, or stale key layout).","commonSituations":"Pointing the loader at the wrong subfolder of a multi-model repo; using a text encoder from a different model version; checkpoints saved with prefixed keys (e.g. 'text_model.') not present in the target architecture.","solutions":["Compare the listed unexpected keys against the model's named parameters and strip/re-map the prefix or stale keys in the checkpoint.","Verify the checkpoint is the correct text-encoder variant for the Ideogram 4 pipeline; re-download the correct one.","Check that the checkpoint is from the repo's text_encoder directory, not the transformer or VAE.","If the keys are from a renamed module, write a conversion function that renames them before load_state_dict."],"exampleFix":"// before\n_, unexpected = model.load_state_dict(sd, strict=False, assign=True)\n// after: strip known foreign prefix\nsd = {k.removeprefix(\"text_model.\"): v for k, v in sd.items()}\n_, unexpected = model.load_state_dict(sd, strict=False, assign=True)","handlingStrategy":"validation","validationCode":"model_keys = {k for k, _ in model.state_dict().items()}\nunexpected = set(sd.keys()) - model_keys\nif unexpected:\n    raise ValueError(f\"checkpoint has foreign keys: {sorted(unexpected)[:10]}\")","typeGuard":"def keys_compatible(sd: dict, model) -> bool:\n    model_keys = set(model.state_dict().keys())\n    return not (set(sd.keys()) - model_keys)","tryCatchPattern":"try:\n    encoder = loader._load_model(cfg, SubModelType.TextEncoder)\nexcept RuntimeError as e:\n    if \"unexpected keys loading Ideogram 4\" in str(e):\n        sd = remap_or_redownload_checkpoint(cfg.path)\n    else:\n        raise","preventionTips":["Preview checkpoint keys against model.state_dict() before loading.","Ensure checkpoints come from the matching subfolder/version of the model repo.","Normalize key prefixes in a conversion step before load_state_dict."],"tags":["weights","checkpoint-mismatch","state-dict"],"backgroundTag":"unexpected-checkpoint-keys","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}