{"record":{"id":"905d0a9db09fe3ac","repo":"invoke-ai/InvokeAI","slug":"krea-2-lora-has-conflicting-layers-that-normalize-905d0a","errorCode":null,"errorMessage":"Krea-2 LoRA has conflicting layers that normalize to the same target '{final_key}' (e.g. both a 'transformer.' and a 'diffusion_model.' alias for one logical layer). This mixed layout is unsupported - refusing to silently drop one of the layers.","messagePattern":"Krea-2 LoRA has conflicting layers that normalize to the same target '(.+?)' \\(e\\.g\\. both a 'transformer\\.' and a 'diffusion_model\\.' alias for one logical layer\\)\\. This mixed layout is unsupported - refusing to silently drop one of the layers\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"invokeai/backend/patches/lora_conversions/krea2_lora_conversion_utils.py","lineNumber":304,"sourceCode":"                clean_key = layer_key[len(prefix) :]\n                is_text_encoder = True\n                break\n        if not is_text_encoder:\n            for prefix in transformer_prefixes:\n                if layer_key.startswith(prefix):\n                    clean_key = layer_key[len(prefix) :]\n                    break\n\n        if is_text_encoder:\n            final_key = f\"{KREA2_LORA_QWEN3VL_PREFIX}{clean_key}\"\n        else:\n            final_key = f\"{KREA2_LORA_TRANSFORMER_PREFIX}{clean_key}\"\n\n        # The `transformer.` and `diffusion_model.` aliases normalize to the same target key. If two source\n        # layers collide here, silently overwriting one would drop weights based on dict ordering, so reject\n        # the mixed-layout adapter explicitly instead.\n        if final_key in layers:\n            raise ValueError(\n                f\"Krea-2 LoRA has conflicting layers that normalize to the same target '{final_key}' \"\n                \"(e.g. both a 'transformer.' and a 'diffusion_model.' alias for one logical layer). \"\n                \"This mixed layout is unsupported - refusing to silently drop one of the layers.\"\n            )\n        layers[final_key] = any_lora_layer_from_state_dict(values)\n\n    return ModelPatchRaw(layers=layers)\n\n\ndef _get_lora_layer_values(\n    layer_key: str, layer_dict: dict[str, torch.Tensor], alpha: float | None\n) -> dict[str, torch.Tensor]:\n    \"\"\"Convert PEFT (lora_A/lora_B) layer values to internal (lora_down/lora_up) format.\"\"\"\n    if \"lora_A.weight\" in layer_dict:\n        if \"lora_B.weight\" not in layer_dict:\n            raise ValueError(\n                f\"Malformed Krea-2 LoRA: layer '{layer_key}' has lora_A.weight but no matching lora_B.weight. \"\n                \"The LoRA file is incomplete or corrupt.\"","sourceCodeStart":286,"sourceCodeEnd":322,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/backend/patches/lora_conversions/krea2_lora_conversion_utils.py#L286-L322","documentation":"Raised in the public lora_model_from_krea2_state_dict entry point. The `transformer.` and `diffusion_model.` prefixes are aliases for the same logical layer; if the state dict contains both, one would be silently overwritten. The loader rejects the mixed-layout adapter explicitly.","triggerScenarios":"Calling lora_model_from_krea2_state_dict with a state dict containing the same layer under both a 'transformer.'-prefixed key and a 'diffusion_model.'-prefixed key, causing identical final_key collisions after prefix stripping.","commonSituations":"ComfyUI-style exports (diffusion_model. prefix) concatenated with diffusers-style exports (transformer. prefix); files assembled from two checkpoints of the same model; automated merge scripts that concatenate state dicts.","solutions":["Strip one alias family from the file so each layer exists under only 'transformer.' or only 'diffusion_model.'.","Re-export the LoRA from the trainer choosing a single prefix convention.","If the two aliases carry different weights, decide which is correct and merge/drop the other explicitly before loading."],"exampleFix":"// before\n'transformer.blocks.0.attn.qkv.lora_down.weight': t1\n'diffusion_model.blocks.0.attn.qkv.lora_down.weight': t2\n// after: keep one alias only\n'transformer.blocks.0.attn.qkv.lora_down.weight': t1","handlingStrategy":"validation","validationCode":"def strip_alias(k: str) -> str:\n    for p in ('transformer.', 'diffusion_model.'):\n        if k.startswith(p):\n            return k[len(p):]\n    return k\nbases = [strip_alias(k) for k in state_dict]\nif len(bases) != len(set(bases)):\n    raise ValueError('both transformer. and diffusion_model. aliases present')","typeGuard":"def uses_single_prefix(state_dict: dict[str, object]) -> bool:\n    prefixes = {k.split('.', 1)[0] for k in state_dict if isinstance(k, str) and '.' in k}\n    return prefixes <= {'transformer'} or prefixes <= {'diffusion_model'}","tryCatchPattern":"try:\n    model = lora_model_from_krea2_state_dict(state_dict)\nexcept ValueError as e:\n    if 'transformer' in str(e) and 'diffusion_model' in str(e):\n        logger.error('Mixed alias prefixes: %s', e)\n        # normalize keys to one prefix and retry\n    else:\n        raise","preventionTips":["Normalize all keys to a single prefix (transformer. or diffusion_model.) before loading.","Never merge ComfyUI-style and diffusers-style exports unchanged.","Sanity-check files with a key-prefix histogram before loading."],"tags":["lora","key-alias","krea2","prefix-collision"],"backgroundTag":"duplicate-key-collision","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}