{"record":{"id":"2109cf7cbba1b8e3","repo":"invoke-ai/InvokeAI","slug":"model-lora-key-is-not-a-wan-lora-resolved-to","errorCode":null,"errorMessage":"Model '{lora_key}' is not a Wan LoRA (resolved to type={getattr(config_type, 'value', config_type)}, base={getattr(config_base, 'value', config_base)}).","messagePattern":"Model '(.+?)' is not a Wan LoRA \\(resolved to type=(.+?), base=(.+?)\\)\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"invokeai/app/invocations/wan_lora_loader.py","lineNumber":49,"sourceCode":"# single-transformer TI2V-5B main, ``_correct_inert_low_routing`` re-points it at\n# the primary list, because that model has no low-noise expert and the alternative\n# is to accept the LoRA and silently do nothing with it. ``both`` and ``high``\n# always reach the primary list, so they are never affected.\nWanLoRATarget = Literal[\"auto\", \"both\", \"high\", \"low\"]\n\n\ndef _assert_is_wan_lora(lora_config: object, lora_key: str) -> None:\n    \"\"\"Reject an identifier whose *resolved* config is not a Wan LoRA.\n\n    The identifier's own ``base``/``type`` fields are client-supplied and cannot be\n    trusted: a hand-authored workflow can label any existing model key as a Wan LoRA\n    and reach model patching (or fail minutes in, after expensive loading). Only the\n    config the key actually resolves to is authoritative.\n    \"\"\"\n    config_type = getattr(lora_config, \"type\", None)\n    config_base = getattr(lora_config, \"base\", None)\n    if config_type is not ModelType.LoRA or config_base is not BaseModelType.Wan:\n        raise ValueError(\n            f\"Model '{lora_key}' is not a Wan LoRA (resolved to \"\n            f\"type={getattr(config_type, 'value', config_type)}, \"\n            f\"base={getattr(config_base, 'value', config_base)}).\"\n        )\n\n\ndef _assert_lora_variant_matches_main(lora_config: object, main_config: object, lora_key: str) -> None:\n    \"\"\"Reject an A14B LoRA wired against a 5B main (and vice versa).\n\n    A mismatch otherwise crashes deep in the layer patcher mid-denoise with an opaque\n    tensor-shape error, after minutes of model loading. Skips silently when either\n    variant is unrecorded (e.g. a LoRA whose targeted layers don't pin the inner dim).\n    \"\"\"\n    lora_variant = getattr(lora_config, \"variant\", None)\n    main_variant = getattr(main_config, \"variant\", None)\n    if lora_variant is None or main_variant is None:\n        return\n    lora_is_5b = lora_variant == WanLoRAVariantType.Wan5B","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/app/invocations/wan_lora_loader.py#L31-L67","documentation":"_assert_is_wan_lora checks the model config the LoRA key actually resolves to and requires type == ModelType.LoRA and base == BaseModelType.Wan. This prevents non-Wan LoRAs (e.g. SDXL or Flux LoRAs) from being patched into a Wan transformer, which would either fail at patching time or silently waste minutes of loading. The error message includes the resolved type and base for diagnosis.","triggerScenarios":"Adding a LoRA whose model-manager record resolves to a non-LoRA type or a non-Wan base (e.g. a main model id, a SDXL LoRA, a Flux LoRA) to wan_lora_loader and calling invoke().","commonSituations":"Copy-pasting a wrong model ID into the LoRA field; the Model Manager record misconfigured (wrong type/base on import); reusing an image-model LoRA list node in a Wan workflow.","solutions":["Point the loader at a model record that resolves to type=LoRA, base=Wan.","Re-scan/import the LoRA in the Model Manager so its type and base are detected correctly.","Remove non-Wan LoRAs from the Wan workflow's loader list."],"exampleFix":"// before\nlora = \"sdxl-detail-lora\"  # base=StableDiffusionXL\nout = wan_lora_loader(loras=[lora], transformer=wan_transformer)  # ValueError\n// after\nlora = \"wan2.1-speed-lora\"  # type=LoRA, base=Wan\nout = wan_lora_loader(loras=[lora], transformer=wan_transformer)","handlingStrategy":"validation","validationCode":"cfg = context.models.get_config(lora_key)\nif cfg is None or cfg.type is not ModelType.LoRA or cfg.base is not BaseModelType.Wan:\n    raise ValueError(f\"{lora_key} is not a Wan LoRA (type={getattr(cfg, 'type', None)}, base={getattr(cfg, 'base', None)})\")","typeGuard":"def is_wan_lora(cfg) -> bool:\n    return (getattr(cfg, 'type', None) is ModelType.LoRA\n            and getattr(cfg, 'base', None) is BaseModelType.Wan)","tryCatchPattern":"try:\n    out = node.invoke(context)\nexcept ValueError as e:\n    if \"is not a Wan LoRA\" in str(e):\n        loras = [k for k in loras if is_wan_lora(get_config(k))]\n        out = replace(node, loras=loras).invoke(context)\n    else:\n        raise","preventionTips":["Import LoRAs through the Model Manager so type/base are auto-detected.","Inspect each LoRA record's type/base before adding to Wan workflows.","Keep Wan LoRAs in a dedicated collection.","Don't reuse image-model LoRA loader nodes for Wan."],"tags":["wan","lora","model-config","validation"],"backgroundTag":"incompatible-lora-model","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}