invoke-ai/InvokeAI · error · NotAMatchError

model does not match Krea-2 LoRA heuristics (no complete lor

Error message

model does not match Krea-2 LoRA heuristics (no complete lora_A/B or lora_down/up pair)

What it means

The Krea-2 LoRA config's _validate_looks_like_lora loads the state dict and requires BOTH that _has_krea2_lora_keys finds Krea-2-specific modules (transformer.text_fusion.* / transformer.transformer_blocks.*) AND that _has_complete_lora_pair finds full lora_A/lora_B (or lora_down/lora_up) pairs. A dora_scale-only file or a file missing one half of every pair fails the suffix check and raises this NotAMatchError.

Source

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

        has_supported_explicit_pair = _has_complete_lora_pair(state_dict, _KREA2_SUPPORTED_LORA_PREFIXES)
        # Reject an orphaned half *anywhere* in the state dict (e.g. a dangling text_fusion half not under
        # the approved prefixes) — it would install here but fail during LoRA conversion at generation time.
        if explicit_krea2_override and has_supported_explicit_pair and _lora_weight_keys_are_all_paired(state_dict):
            return cls(**override_fields)

        cls._validate_looks_like_lora(mod)
        cls._validate_base(mod)
        return cls(**override_fields)

    @classmethod
    def _validate_looks_like_lora(cls, mod: ModelOnDisk) -> None:
        """Krea-2 LoRAs have keys like transformer.text_fusion.* / transformer.transformer_blocks.* with
        a lora_A/lora_B (or lora_down/lora_up) suffix. The text-fusion stage is unique to Krea-2."""
        state_dict = mod.load_state_dict()
        # Require a *complete* lora_A/B (or lora_down/up) pair, not merely any lora/dora suffix: a file with
        # only ``dora_scale`` and no A/B weights would pass a suffix check but fail later on missing weights.
        if not (_has_krea2_lora_keys(state_dict) and _has_complete_lora_pair(state_dict)):
            raise NotAMatchError(
                "model does not match Krea-2 LoRA heuristics (no complete lora_A/B or lora_down/up pair)"
            )
        # Reject a file with an orphaned LoRA half (a valid layer plus a dangling lora_A/B/down/up); it
        # would install here but fail later during LoRA conversion.
        if not _lora_weight_keys_are_all_paired(state_dict):
            raise NotAMatchError("Krea-2 LoRA has an incomplete lora_A/B (or lora_down/up) weight pair")

    @classmethod
    def _get_base_or_raise(cls, mod: ModelOnDisk) -> BaseModelType:
        if _has_krea2_lora_keys(mod.load_state_dict()):
            return BaseModelType.Krea2
        raise NotAMatchError("model does not look like a Krea-2 LoRA")


class LoRA_LyCORIS_Anima_Config(LoRA_LyCORIS_Config_Base, Config_Base):
    """Model config for Anima LoRA models in LyCORIS format."""

    base: Literal[BaseModelType.Anima] = Field(default=BaseModelType.Anima)

View on GitHub (pinned to 0b6a024f2f)

Solutions

  1. Re-download the LoRA file and compare checksum/size; a missing pair usually means truncation or a bad export.
  2. Inspect keys: confirm each layer has both lora_A+lora_B (or lora_down+lora_up) tensors; re-export the LoRA including both halves.
  3. If the file is a DoRA-only or non-standard export, convert it to a standard LoRA (both halves) before installing.
  4. Check that this is truly a Krea-2 LoRA and not a checkpoint for another format whose config class should claim it.

Example fix

// before
installer.install(path="krea2_lora.safetensors")  # raises NotAMatchError
// after: require a complete pair per layer before installing
from safetensors import safe_open
with safe_open("krea2_lora.safetensors", framework="pt") as f:
    ks = set(f.keys())
has_krea2 = any("text_fusion" in k or "transformer_blocks" in k for k in ks)
ab_pairs = {k.rsplit(".", 1)[0] for k in ks if k.endswith(("lora_A", "lora_B", "lora_down", "lora_up"))}
complete = all({f"{b}.lora_A", f"{b}.lora_B"} <= ks or {f"{b}.lora_down", f"{b}.lora_up"} <= ks for b in ab_pairs)
if has_krea2 and complete:
    installer.install(path="krea2_lora.safetensors")
Defensive patterns

Strategy: validation

Validate before calling

from safetensors import safe_open

def probe_krea2_lora(path):
    with safe_open(path, framework="pt") as f:
        ks = set(f.keys())
    has_krea2 = any("text_fusion" in k or "time_mod_proj" in k or "transformer_blocks" in k for k in ks)
    bases = {k.rsplit(".", 1)[0] for k in ks if k.endswith(("lora_A", "lora_B", "lora_down", "lora_up"))}
    complete = bool(bases) and all(
        {f"{b}.lora_A", f"{b}.lora_B"} <= ks or {f"{b}.lora_down", f"{b}.lora_up"} <= ks for b in bases
    )
    return has_krea2 and complete

assert probe_krea2_lora("krea2_lora.safetensors"), "missing complete lora_A/B pair — do not install as Krea-2 LoRA"

Type guard

def has_complete_lora_pair(keys: set[str]) -> bool:
    bases = {k.rsplit(".", 1)[0] for k in keys if k.endswith(("lora_A", "lora_B", "lora_down", "lora_up"))}
    return bool(bases) and all(
        {f"{b}.lora_A", f"{b}.lora_B"} <= keys or {f"{b}.lora_down", f"{b}.lora_up"} <= keys for b in bases
    )

Try / catch

try:
    installer.install(path="krea2_lora.safetensors")
except NotAMatchError as e:
    if "no complete lora_A/B" in str(e):
        log.error("Krea-2 LoRA incomplete (DoRA-only or truncated): %s", e)
        raise ModelImportRejected("re-download or re-export with both LoRA halves") from e
    raise

Prevention

When it happens

Trigger: from_model_on_disk validation of a candidate Krea-2 LoRA where the state dict has text_fusion/transformer_blocks keys but no lora_A/B or lora_down/up suffixes, or contains only dora_scale entries without A/B weight tensors.

Common situations: Downloading a truncated/partially-uploaded safetensors file; DoRA-style exports that ship only dora_scale; converted exports that dropped the down/up weight tensors; pointing a Krea-2 full-model checkpoint (no LoRA suffixes at all) at the LoRA config class.

Related errors


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