{"record":{"id":"3287d13bdb7446c3","repo":"invoke-ai/InvokeAI","slug":"krea-2-lora-has-an-incomplete-lora-a-b-or-lora-do","errorCode":null,"errorMessage":"Krea-2 LoRA has an incomplete lora_A/B (or lora_down/up) weight pair","messagePattern":"Krea-2 LoRA has an incomplete lora_A/B \\(or lora_down/up\\) weight pair","errorType":"exception","errorClass":"NotAMatchError","httpStatus":null,"severity":"error","filePath":"invokeai/backend/model_manager/configs/lora.py","lineNumber":1010,"sourceCode":"        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)\n\n    @classmethod\n    def _validate_looks_like_lora(cls, mod: ModelOnDisk) -> None:\n        \"\"\"Anima LoRAs use Kohya-style keys targeting Cosmos DiT blocks.\n\n        Anima LoRAs have keys like:","sourceCodeStart":992,"sourceCodeEnd":1028,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/backend/model_manager/configs/lora.py#L992-L1028","documentation":"Immediately after the heuristic pair check, the Krea-2 LoRA config runs _lora_weight_keys_are_all_paired to reject files containing an ORPHANED LoRA half: at least one valid layer plus a dangling lora_A/lora_B/lora_down/lora_up with no counterpart. Such a file would pass the initial check but crash later during LoRA conversion, so it is rejected up front with this NotAMatchError.","triggerScenarios":"from_model_on_disk validation where the state dict contains one or more lora_A/lora_B (or lora_down/lora_up) keys whose sibling tensor is absent — e.g. a layer with only lora_down and no lora_up.","commonSituations":"Partially written or interrupted download; hand-edited or pruned LoRA exports that dropped one tensor to save space; merging scripts that concatenated key sets from two LoRAs and dropped duplicates incorrectly; corrupted safetensors headers after a failed save.","solutions":["Re-download or re-export the LoRA; an orphaned half almost always means a corrupted or mis-merged file.","Scan keys and find the layer(s) missing their sibling tensor (lora_A without lora_B, lora_down without lora_up), then remove the dangling keys or restore the missing tensor before installing.","Re-merge the LoRA from its original training checkpoint so every layer is complete.","If only one layer is broken, prune that layer entirely (the LoRA degrades gracefully) and reinstall."],"exampleFix":"// before: orphaned half crashes conversion later\ninstaller.install(path=\"krea2_lora.safetensors\")\n// after: detect and prune orphaned halves first\nfrom safetensors import safe_open\nwith safe_open(\"krea2_lora.safetensors\", framework=\"pt\") as f:\n    ks = set(f.keys())\nfor base in {k.rsplit(\".\", 1)[0] for k in ks if any(k.endswith(s) for s in (\"lora_A\", \"lora_B\", \"lora_down\", \"lora_up\"))}:\n    pair = {f\"{base}.lora_A\", f\"{base}.lora_B\"} <= ks or {f\"{base}.lora_down\", f\"{base}.lora_up\"} <= ks\n    assert pair, f\"orphaned LoRA half at {base}\"","handlingStrategy":"validation","validationCode":"from safetensors import safe_open\n\ndef find_orphaned_lora_halves(path):\n    with safe_open(path, framework=\"pt\") as f:\n        ks = set(f.keys())\n    suffixes = (\"lora_A\", \"lora_B\", \"lora_down\", \"lora_up\")\n    orphans = []\n    for k in (k for k in ks if any(k.endswith(s) for s in suffixes)):\n        base = k.rsplit(\".\", 1)[0]\n        if not ({f\"{base}.lora_A\", f\"{base}.lora_B\"} <= ks or {f\"{base}.lora_down\", f\"{base}.lora_up\"} <= ks):\n            orphans.append(base)\n    return orphans\n\nassert not find_orphaned_lora_halves(\"krea2_lora.safetensors\"), \"file contains orphaned LoRA halves\"","typeGuard":"def lora_keys_all_paired(keys: set[str]) -> bool:\n    suffixes = (\"lora_A\", \"lora_B\", \"lora_down\", \"lora_up\")\n    for k in (k for k in keys if any(k.endswith(s) for s in suffixes)):\n        base = k.rsplit(\".\", 1)[0]\n        if not ({f\"{base}.lora_A\", f\"{base}.lora_B\"} <= keys or {f\"{base}.lora_down\", f\"{base}.lora_up\"} <= keys):\n            return False\n    return True","tryCatchPattern":"try:\n    installer.install(path=\"krea2_lora.safetensors\")\nexcept NotAMatchError as e:\n    if \"incomplete lora_A/B\" in str(e):\n        log.error(\"orphaned LoRA half in file: %s\", e)\n        cleaned = strip_orphaned_halves(\"krea2_lora.safetensors\")  # drop dangling keys or re-export\n        installer.install(path=cleaned)\n    else:\n        raise","preventionTips":["Never hand-edit or partially prune LoRA safetensors files; drop whole layers, not single tensors.","Check merge/prune scripts so duplicate-key handling cannot drop one half of a pair.","Re-download instead of repairing a suspicious file; orphaned halves usually mean a bad write.","Run the pairing scan above as a pre-install gate in your model pipeline."],"tags":["invokeai","model-manager","lora","krea2","corrupt-weights","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"}