invoke-ai/InvokeAI · error · NotAMatchError

model does not look like an Anima LoRA

Error message

model does not look like an Anima LoRA

What it means

NotAMatchError raised by LoRA_LyCORIS_Anima_Config._get_base_or_raise when a candidate LyCORIS LoRA's state-dict keys fail both strict Cosmos-DiT detectors (Kohya and PEFT/diffusers forms). Anima LoRAs target Cosmos DiT blocks (blocks.X.mlp, adaln_modulation, cross_attn.q_proj etc.); the strict detectors require one of those Anima-exclusive subcomponent names so detection stays mutually exclusive with Wan LoRAs. The error is part of InvokeAI's first-match-wins model probing: each config class raises it to say 'this file is not mine' so the probe can try the next class.

Source

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

            return

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

    @classmethod
    def _get_base_or_raise(cls, mod: ModelOnDisk) -> BaseModelType:
        """Anima LoRAs target Cosmos DiT blocks (blocks.X.mlp, blocks.X.adaln_modulation,
        blocks.X.cross_attn.q_proj, etc.).

        Uses the strict Cosmos-DiT detectors to be mutually exclusive with
        Wan-LoRA detection — see ``_validate_looks_like_lora`` for rationale.
        """
        state_dict = mod.load_state_dict()
        str_keys = [k for k in state_dict.keys() if isinstance(k, str)]

        if has_cosmos_dit_kohya_keys_strict(str_keys) or has_cosmos_dit_peft_keys_strict(str_keys):
            return BaseModelType.Anima

        raise NotAMatchError("model does not look like an Anima LoRA")


class LoRA_LyCORIS_Wan_Config(LoRA_LyCORIS_Config_Base, Config_Base):
    """Model config for Wan 2.2 LoRA models in LyCORIS format.

    Wan LoRAs target ``WanTransformer3DModel`` blocks. The Wan 2.2 A14B family
    is dual-expert (high-noise + low-noise) — LoRAs are typically trained
    against one expert. ``expert`` records which one so the model loader
    invocation can wire it to the correct ``loras`` / ``loras_low_noise`` list.
    Many LoRAs are expert-agnostic (TI2V-5B family, or community LoRAs that
    just don't tag the expert) — these get ``expert=None`` and are applied to
    both experts by default.
    """

    base: Literal[BaseModelType.Wan] = Field(default=BaseModelType.Wan)
    expert: Literal["high", "low"] | None = Field(
        default=None,
        description="For Wan 2.2 A14B dual-expert LoRAs: 'high' targets the high-noise expert, "

View on GitHub (pinned to 0b6a024f2f)

Solutions

  1. Verify the file actually is an Anima (Cosmos DiT) LoRA; if it targets another architecture, it should be matched by a different config class — ensure the file name/type hints (lora_prefix, directory placement) route it correctly.
  2. Inspect the state dict keys (python: safetensors.torch.load_file(...).keys()) and confirm they contain Anima-exclusive names like blocks.*.mlp, adaln_modulation, or cross_attn.*_proj with lora_down/lora_A suffixes.
  3. If the LoRA is from a different trainer, re-export/convert it with the standard Kohya or diffusers PEFT key layout so the strict detectors match.
  4. Check InvokeAI version — strict detectors were added to fix Anima/Wan cross-matching; update if you have an older or newer key-naming scheme mismatch.

Example fix

// before: keys like 'lora_unet_cross_attn.q.lora_down.weight' (bare .q/.k/.v/.o => Wan-style)
// after: convert to Anima/Cosmos names, e.g.
// 'lora_unet_blocks_0_cross_attn.k_proj.lora_down.weight'
// or diffusers form 'transformer.blocks.0.mlp.layer_0.lora_A.weight'
Defensive patterns

Strategy: validation

Validate before calling

from safetensors.torch import load_file
sd = load_file(path)  # or zip/torch load for .ckpt
keys = [k for k in sd.keys() if isinstance(k, str)]
is_anima_lora = (
    any(('mlp' in k or 'adaln_modulation' in k or k.rstrip().endswith(('_proj.lora_down.weight', '_proj.lora_A.weight'))) for k in keys)
)
if not is_anima_lora:
    raise ValueError(f'{path} is not an Anima (Cosmos DiT) LoRA')

Type guard

def is_anima_lora_state_dict(keys: list[str]) -> bool:
    return any(
        ('mlp' in k or 'adaln_modulation' in k or '_proj' in k)
        and (k.endswith(('lora_down.weight', 'lora_A.weight', 'lora_up.weight', 'lora_B.weight')))
        for k in keys
    )

Try / catch

from invokeai.backend.model_manager.errors import NotAMatchError
try:
    config = install_model(path)
except NotAMatchError as e:
    logger.warning('Not an Anima LoRA: %s', e)
    config = probe_with_next_config(path)  # fall through to Wan/FLUX/etc.

Prevention

When it happens

Trigger: Calling the model-install/probe path (e.g. ModelInstallService or _get_base_or_raise via _validate_base) on a file the router offers to LoRA_LyCORIS_Anima_Config whose state_dict contains no keys matching has_cosmos_dit_kohya_keys_strict or has_cosmos_dit_peft_keys_strict — e.g. a Wan, FLUX, or SD LoRA, or a Cosmos LoRA saved with loose/renamed key layouts lacking mlp/adaln_modulation/_proj-suffixed attention names.

Common situations: Downloading a Wan 2.2 or FLUX LoRA that gets routed into the LyCORIS Anima probe first; training a Cosmos-DiT LoRA with a script that emits non-standard or trimmed key names; loading a legacy/renamed checkpoint after a LoRA-conversion tool rewrote keys.

Related errors


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