{"record":{"id":"0c7f9447b2761729","repo":"invoke-ai/InvokeAI","slug":"model-does-not-match-krea-2-lora-heuristics-no-co","errorCode":null,"errorMessage":"model does not match Krea-2 LoRA heuristics (no complete lora_A/B or lora_down/up pair)","messagePattern":"model does not match Krea-2 LoRA heuristics \\(no complete lora_A/B or lora_down/up pair\\)","errorType":"exception","errorClass":"NotAMatchError","httpStatus":null,"severity":"error","filePath":"invokeai/backend/model_manager/configs/lora.py","lineNumber":1004,"sourceCode":"        has_supported_explicit_pair = _has_complete_lora_pair(state_dict, _KREA2_SUPPORTED_LORA_PREFIXES)\n        # Reject an orphaned half *anywhere* in the state dict (e.g. a dangling text_fusion half not under\n        # the approved prefixes) — it would install here but fail during LoRA conversion at generation time.\n        if explicit_krea2_override and has_supported_explicit_pair and _lora_weight_keys_are_all_paired(state_dict):\n            return cls(**override_fields)\n\n        cls._validate_looks_like_lora(mod)\n        cls._validate_base(mod)\n        return cls(**override_fields)\n\n    @classmethod\n    def _validate_looks_like_lora(cls, mod: ModelOnDisk) -> None:\n        \"\"\"Krea-2 LoRAs have keys like transformer.text_fusion.* / transformer.transformer_blocks.* with\n        a lora_A/lora_B (or lora_down/lora_up) suffix. The text-fusion stage is unique to Krea-2.\"\"\"\n        state_dict = mod.load_state_dict()\n        # Require a *complete* lora_A/B (or lora_down/up) pair, not merely any lora/dora suffix: a file with\n        # only ``dora_scale`` and no A/B weights would pass a suffix check but fail later on missing weights.\n        if not (_has_krea2_lora_keys(state_dict) and _has_complete_lora_pair(state_dict)):\n            raise NotAMatchError(\n                \"model does not match Krea-2 LoRA heuristics (no complete lora_A/B or lora_down/up pair)\"\n            )\n        # Reject a file with an orphaned LoRA half (a valid layer plus a dangling lora_A/B/down/up); it\n        # would install here but fail later during LoRA conversion.\n        if not _lora_weight_keys_are_all_paired(state_dict):\n            raise NotAMatchError(\"Krea-2 LoRA has an incomplete lora_A/B (or lora_down/up) weight pair\")\n\n    @classmethod\n    def _get_base_or_raise(cls, mod: ModelOnDisk) -> BaseModelType:\n        if _has_krea2_lora_keys(mod.load_state_dict()):\n            return BaseModelType.Krea2\n        raise NotAMatchError(\"model does not look like a Krea-2 LoRA\")\n\n\nclass LoRA_LyCORIS_Anima_Config(LoRA_LyCORIS_Config_Base, Config_Base):\n    \"\"\"Model config for Anima LoRA models in LyCORIS format.\"\"\"\n\n    base: Literal[BaseModelType.Anima] = Field(default=BaseModelType.Anima)","sourceCodeStart":986,"sourceCodeEnd":1022,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/backend/model_manager/configs/lora.py#L986-L1022","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Re-download the LoRA file and compare checksum/size; a missing pair usually means truncation or a bad export.","Inspect keys: confirm each layer has both lora_A+lora_B (or lora_down+lora_up) tensors; re-export the LoRA including both halves.","If the file is a DoRA-only or non-standard export, convert it to a standard LoRA (both halves) before installing.","Check that this is truly a Krea-2 LoRA and not a checkpoint for another format whose config class should claim it."],"exampleFix":"// before\ninstaller.install(path=\"krea2_lora.safetensors\")  # raises NotAMatchError\n// after: require a complete pair per layer before installing\nfrom safetensors import safe_open\nwith safe_open(\"krea2_lora.safetensors\", framework=\"pt\") as f:\n    ks = set(f.keys())\nhas_krea2 = any(\"text_fusion\" in k or \"transformer_blocks\" in k for k in ks)\nab_pairs = {k.rsplit(\".\", 1)[0] for k in ks if k.endswith((\"lora_A\", \"lora_B\", \"lora_down\", \"lora_up\"))}\ncomplete = 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)\nif has_krea2 and complete:\n    installer.install(path=\"krea2_lora.safetensors\")","handlingStrategy":"validation","validationCode":"from safetensors import safe_open\n\ndef probe_krea2_lora(path):\n    with safe_open(path, framework=\"pt\") as f:\n        ks = set(f.keys())\n    has_krea2 = any(\"text_fusion\" in k or \"time_mod_proj\" in k or \"transformer_blocks\" in k for k in ks)\n    bases = {k.rsplit(\".\", 1)[0] for k in ks if k.endswith((\"lora_A\", \"lora_B\", \"lora_down\", \"lora_up\"))}\n    complete = bool(bases) and all(\n        {f\"{b}.lora_A\", f\"{b}.lora_B\"} <= ks or {f\"{b}.lora_down\", f\"{b}.lora_up\"} <= ks for b in bases\n    )\n    return has_krea2 and complete\n\nassert probe_krea2_lora(\"krea2_lora.safetensors\"), \"missing complete lora_A/B pair — do not install as Krea-2 LoRA\"","typeGuard":"def has_complete_lora_pair(keys: set[str]) -> bool:\n    bases = {k.rsplit(\".\", 1)[0] for k in keys if k.endswith((\"lora_A\", \"lora_B\", \"lora_down\", \"lora_up\"))}\n    return bool(bases) and all(\n        {f\"{b}.lora_A\", f\"{b}.lora_B\"} <= keys or {f\"{b}.lora_down\", f\"{b}.lora_up\"} <= keys for b in bases\n    )","tryCatchPattern":"try:\n    installer.install(path=\"krea2_lora.safetensors\")\nexcept NotAMatchError as e:\n    if \"no complete lora_A/B\" in str(e):\n        log.error(\"Krea-2 LoRA incomplete (DoRA-only or truncated): %s\", e)\n        raise ModelImportRejected(\"re-download or re-export with both LoRA halves\") from e\n    raise","preventionTips":["Verify file size/checksum after download; incomplete pairs usually indicate truncation.","Reject DoRA-only exports that carry dora_scale but no lora_A/B weight tensors.","Re-export conversions from the original training checkpoint rather than round-tripping partial files.","Pre-flight the key set for paired lora_A/B or lora_down/up before install."],"tags":["invokeai","model-manager","lora","krea2","not-a-match","model-install"],"backgroundTag":"lora-not-a-match","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}