invoke-ai/InvokeAI · error · NotAMatchError

model does not match Wan LoRA heuristics

Error message

model does not match Wan LoRA heuristics

What it means

NotAMatchError raised by LoRA_LyCORIS_Wan_Config._validate_looks_like_lora when a candidate file fails the Wan LoRA heuristic test: it must simultaneously have Wan-style keys (has_wan_kohya_keys or has_wan_peft_keys), a LoRA/LoKR weight suffix (lora_A.weight, lora_down.weight, dora_scale, lokr_w1, etc.), and NO non-Wan architecture signature keys. This guard prevents Anima/Wan cross-identification caused by shared cross_attn/self_attn naming. It is thrown during from_model_on_disk probing so the router can fall through to other config classes.

Source

Thrown at invokeai/backend/model_manager/configs/lora.py:1136

            state_dict,
            {
                "lora_A.weight",
                "lora_B.weight",
                "lora_down.weight",
                "lora_up.weight",
                "dora_scale",
                ".lokr_w1",
                ".lokr_w2",
            },
        )

        # Reject if any non-Wan architecture signature is present. Without this
        # guard a Wan LoRA could be falsely identified by Anima (cross_attn /
        # self_attn name collision) or vice versa.
        if has_wan_keys and has_lora_suffix and not has_non_wan_architecture_keys(str_keys):
            return

        raise NotAMatchError("model does not match Wan LoRA heuristics")

    @classmethod
    def _get_base_or_raise(cls, mod: ModelOnDisk) -> BaseModelType:
        state_dict = mod.load_state_dict()
        str_keys = [k for k in state_dict.keys() if isinstance(k, str)]

        if (has_wan_kohya_keys(str_keys) or has_wan_peft_keys(str_keys)) and not has_non_wan_architecture_keys(
            str_keys
        ):
            return BaseModelType.Wan

        raise NotAMatchError("model does not look like a Wan LoRA")

    @classmethod
    def from_model_on_disk(cls, mod: ModelOnDisk, override_fields: dict[str, Any]) -> Self:
        # Run the base-class probe (file-check, lora-suffix, base detection).
        instance = super().from_model_on_disk(mod, override_fields)

View on GitHub (pinned to 0b6a024f2f)

Solutions

  1. Confirm the file is a Wan LoRA (keys like blocks.*.self_attn / attn1 / ffn.net with lora_down.weight or lora_A.weight suffixes); if it's a main model or another architecture's LoRA, install it through the right import path/category.
  2. Inspect state-dict keys with safetensors and check for foreign architecture signatures (mlp, adaln_modulation, *_proj) that trip has_non_wan_architecture_keys; rename/convert keys if mislabeled.
  3. If it's a DoRA/LoKR variant, make sure suffixes (dora_scale, lokr_w1/w2) survived export; re-export with standard Kohya/LyCORIS tooling.
  4. If you believe the file IS a Wan LoRA, file an issue with the key list — the heuristic may need a new pattern.

Example fix

// before (Anima-flavored key, rejected by Wan probe)
// 'lora_unet_blocks_0_cross_attn.k_proj.lora_down.weight'
// after (Wan-style key)
// 'lora_unet_blocks_0_cross_attn.k.lora_down.weight'
Defensive patterns

Strategy: validation

Validate before calling

from safetensors.torch import load_file
sd = load_file(path)
keys = list(sd.keys())
has_wan = any(('attn1' in k or 'attn2' in k or 'ffn.net' in k or 'self_attn' in k or 'cross_attn' in k) for k in keys)
has_lora_suffix = any(k.endswith(('lora_A.weight', 'lora_B.weight', 'lora_down.weight', 'lora_up.weight', 'dora_scale', '.lokr_w1', '.lokr_w2')) for k in keys)
foreign = any(('adaln_modulation' in k or ('_proj' in k and 'cross_attn' in k)) for k in keys)
if not (has_wan and has_lora_suffix and not foreign):
    raise ValueError(f'{path} does not satisfy Wan LoRA heuristics')

Type guard

def looks_like_wan_lora(keys: list[str]) -> bool:
    wan = any(('self_attn' in k or 'cross_attn' in k or 'attn1' in k or 'attn2' in k or 'ffn' in k) for k in keys)
    suffix = any(k.endswith(('lora_down.weight', 'lora_A.weight', 'dora_scale', 'lokr_w1', 'lokr_w2')) for k in keys)
    return wan and suffix and not any(('adaln_modulation' in k or 'mlp.layer_0.lora' in k) for k in keys)

Try / catch

try:
    instance = LoRA_LyCORIS_Wan_Config.from_model_on_disk(mod, overrides)
except NotAMatchError as e:
    logger.info('File rejected as Wan LoRA: %s', e)
    instance = try_other_lora_configs(mod, overrides)

Prevention

When it happens

Trigger: Probing a file via from_model_on_disk where any of the three conditions fails: (1) keys do not match Wan kohya/peft patterns (attn1/attn2/ffn.net or self_attn/cross_attn/ffn.N), (2) no lora_A/lora_down/dora_scale/lokr suffixes present (e.g. a full main-model checkpoint, not a LoRA), or (3) has_non_wan_architecture_keys finds signatures of another architecture (e.g. Anima _proj-suffixed attention or mlp/adaln_modulation names).

Common situations: Pointing the installer at a full Wan transformer checkpoint instead of a LoRA; a mixed/multi-architecture LoRA dump; a LyCORIS file with unusual suffixes; an Anima LoRA being probed and correctly rejected by the Wan class (the error itself is expected probe behavior when the file is simply not a Wan LoRA).

Related errors


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