{"record":{"id":"3bbc111d7ad4c1be","repo":"invoke-ai/InvokeAI","slug":"model-does-not-look-like-a-wan-lora","errorCode":null,"errorMessage":"model does not look like a Wan LoRA","messagePattern":"model does not look like a Wan LoRA","errorType":"exception","errorClass":"NotAMatchError","httpStatus":null,"severity":"error","filePath":"invokeai/backend/model_manager/configs/lora.py","lineNumber":1148,"sourceCode":"        # Reject if any non-Wan architecture signature is present. Without this\n        # guard a Wan LoRA could be falsely identified by Anima (cross_attn /\n        # self_attn name collision) or vice versa.\n        if has_wan_keys and has_lora_suffix and not has_non_wan_architecture_keys(str_keys):\n            return\n\n        raise NotAMatchError(\"model does not match Wan LoRA heuristics\")\n\n    @classmethod\n    def _get_base_or_raise(cls, mod: ModelOnDisk) -> BaseModelType:\n        state_dict = mod.load_state_dict()\n        str_keys = [k for k in state_dict.keys() if isinstance(k, str)]\n\n        if (has_wan_kohya_keys(str_keys) or has_wan_peft_keys(str_keys)) and not has_non_wan_architecture_keys(\n            str_keys\n        ):\n            return BaseModelType.Wan\n\n        raise NotAMatchError(\"model does not look like a Wan LoRA\")\n\n    @classmethod\n    def from_model_on_disk(cls, mod: ModelOnDisk, override_fields: dict[str, Any]) -> Self:\n        # Run the base-class probe (file-check, lora-suffix, base detection).\n        instance = super().from_model_on_disk(mod, override_fields)\n\n        # Auto-detect the model-family variant from inner_dim in the state\n        # dict. The override field skips this if the user has set it.\n        #\n        # Resolved *before* the expert tag because the expert is only meaningful for\n        # A14B — see below.\n        if instance.variant is None:\n            instance.variant = detect_wan_lora_variant(mod.load_state_dict())\n\n        # Auto-detect the expert tag from the filename if the user didn't override\n        # it, using the same helper as the transformer probes so the two can't drift\n        # apart. That also picks up the bare ``HIGH``/``LOW`` convention, which\n        # matters here: an expert-specific LoRA left untagged is applied to *both*","sourceCodeStart":1130,"sourceCodeEnd":1166,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/backend/model_manager/configs/lora.py#L1130-L1166","documentation":"NotAMatchError raised by LoRA_LyCORIS_Wan_Config._get_base_or_raise when the state dict does not identify as a Wan-base LoRA: either no Wan kohya/peft keys are present, or has_non_wan_architecture_keys detects another architecture's signatures. Called from _validate_base during from_model_on_disk; the class raises to signal 'not a Wan LoRA' so probing continues with other configs.","triggerScenarios":"from_model_on_disk -> _validate_base -> _get_base_or_raise on a file whose str_keys lack Wan patterns (attn1/attn2/ffn.net diffusers form or self_attn/cross_attn/ffn.N native form), or which contains keys flagged as non-Wan architecture (e.g. Anima mlp/adaln_modulation/_proj names).","commonSituations":"Installing a non-Wan LoRA that the router offered to the Wan config; a Wan LoRA converted by a tool that renamed keys away from the expected layout; files mixing architectures after manual merging of state dicts.","solutions":["Verify the LoRA's architecture; if it is Anima/FLUX/SD, let a different config class pick it up (fix routing hints like install type or folder).","Dump keys via safetensors.torch.load_file and confirm Wan naming (self_attn/cross_attn/ffn.N or attn1/attn2/ffn.net) without foreign signatures.","Re-export the LoRA with the standard Kohya or diffusers PEFT key layout if a converter mangled the names.","Update InvokeAI or open an issue with the key list if your trainer emits a legitimate new Wan key pattern the detectors miss."],"exampleFix":"// before (foreign signature present, base detection fails)\n// keys: ['transformer.blocks.0.mlp.layer_0.lora_A.weight', ...]\n// after (pure Wan keys)\n// keys: ['lora_unet_blocks_0_self_attn.k.lora_down.weight', ...]","handlingStrategy":"validation","validationCode":"from safetensors.torch import load_file\nkeys = [k for k in load_file(path).keys() if isinstance(k, str)]\nwan_ok = any(('self_attn' in k or 'cross_attn' in k or 'attn1' in k or 'ffn' in k) for k in keys)\nforeign = any(('adaln_modulation' in k or 'mlp.layer_0' in k or '_proj.lora' in k) for k in keys)\nif not (wan_ok and not foreign):\n    raise ValueError(f'{path} is not recognized as a Wan-base LoRA')","typeGuard":"def is_wan_base_lora(keys: list[str]) -> bool:\n    has_wan_keys = any(('self_attn' in k or 'cross_attn' in k or 'attn1' in k or 'attn2' in k) for k in keys)\n    no_foreign = not any(('adaln_modulation' in k or 'blocks_0_mlp' in k or '_proj.' in k) for k in keys)\n    return has_wan_keys and no_foreign","tryCatchPattern":"try:\n    base = LoRA_LyCORIS_Wan_Config._get_base_or_raise(mod)\nexcept NotAMatchError:\n    base = fallback_detect_base(mod)  # try other config classes","preventionTips":["Verify the LoRA's target model family before install (Wan 2.1/2.2 vs Anima/Cosmos).","Re-export through standard tooling if a converter renamed keys.","Inspect state-dict keys when a download's provenance is unclear.","Pin InvokeAI versions in pipelines where probe behavior changes between releases."],"tags":["model-manager","lora","base-detection","invokeai"],"backgroundTag":"model-format-not-matched","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}