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.

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.

Appendix: 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)