{"record":{"id":"0a466f29fcb165cf","repo":"invoke-ai/InvokeAI","slug":"krea-2-lora-has-conflicting-layers-that-normalize-0a466f","errorCode":null,"errorMessage":"Krea-2 LoRA has conflicting layers that normalize to the same target '{converted_key}' (from '{source_keys[converted_key]}' and '{key}'). 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 '(.+?)' \\(from '(.+?)' and '(.+?)'\\)\\. 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":232,"sourceCode":"    converted_state_dict: Dict[str, torch.Tensor] = {}\n    source_keys: dict[str, str] = {}\n    for key, value in state_dict.items():\n        converted_key = key\n        if isinstance(key, str) and key.startswith(_KREA2_KOHYA_PREFIX):\n            # The flattened module path runs up to the first '.'; the weight suffix (``lora_down.weight``,\n            # ``alpha``, ...) follows it. Some writers emit a doubled separator after the prefix.\n            flat_path, dot, weight_suffix = key[len(_KREA2_KOHYA_PREFIX) :].lstrip(\"_\").partition(\".\")\n            module_path = _unflatten_kohya_krea2_module_path(flat_path)\n            # Only rewrite when ``_group_by_layer`` can split the suffix back off. Un-flattening introduces\n            # dots into the module path, and the grouper's fallback for an unknown suffix is a blind\n            # ``rsplit(\".\", 2)`` — on a dotted path that cuts *inside the module name*, fusing two modules\n            # into one bogus layer that aborts the whole load. LyCORIS suffixes such as ``.lokr_w1`` or\n            # ``.hada_w1_a`` hit exactly that. Flattened, they have no interior dot and group harmlessly,\n            # so leaving them verbatim keeps them at the pre-existing warn-and-skip behaviour.\n            if module_path is not None and flat_path in fully_convertible_flat_paths:\n                converted_key = f\"{module_path}{dot}{weight_suffix}\"\n        if converted_key in converted_state_dict:\n            raise ValueError(\n                f\"Krea-2 LoRA has conflicting layers that normalize to the same target '{converted_key}' \"\n                f\"(from '{source_keys[converted_key]}' and '{key}'). This mixed layout is unsupported - \"\n                \"refusing to silently drop one of the layers.\"\n            )\n        converted_state_dict[converted_key] = value\n        source_keys[converted_key] = str(key)\n    return converted_state_dict\n\n\ndef is_state_dict_likely_krea2_lora(state_dict: dict[str | int, torch.Tensor]) -> bool:\n    \"\"\"Checks if the provided state dict is likely a Krea-2 LoRA.\n\n    Requires the distinctive Krea-2 ``text_fusion`` / ``txtfusion`` / ``time_mod_proj`` modules so it does not\n    false-match Qwen-Image or Z-Image LoRAs that also carry ``transformer.transformer_blocks.`` keys.\n    \"\"\"\n    str_keys = [k for k in state_dict.keys() if isinstance(k, str)]\n    has_krea2_module = any(any(sig in k for sig in KREA2_TRANSFORMER_SIGNATURE_KEYS) for k in str_keys)\n    has_lora_suffix = any(","sourceCodeStart":214,"sourceCodeEnd":250,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/backend/patches/lora_conversions/krea2_lora_conversion_utils.py#L214-L250","documentation":"Raised while converting a Kohya-layout Krea-2 LoRA state dict. After mapping kohya keys to diffusers-style keys, two source keys normalize to the same converted target key, which would silently overwrite one layer. The loader raises instead of dropping weights.","triggerScenarios":"lora_model_from_krea2_state_dict -> _maybe_convert_kohya_krea2_state_dict with a state dict where two kohya keys (after module_path/weight_suffix normalization, e.g. differing only in suffixes like .lokr_w1 vs a standard lora_down weight) collapse to the same converted_key.","commonSituations":"Kohya-exported files that contain both an alpha-style and a full-weight entry for the same module; LyCORIS files mixed with plain LoRA keys; checkpoints merged from two sources that each define the same layer.","solutions":["Inspect the file's keys and delete the duplicate entries so only one key normalizes to each target.","Regenerate the LoRA export with a single layout (plain Kohya LoRA without LyCORIS-style extra tensors for the same modules).","Split the file: load the LyCORIS part with a LyCORIS-aware loader and the plain LoRA part here."],"exampleFix":"// before (colliding keys in one file)\n'lora_unet_blocks_0_attn_qkv.alpha'\n'lora_unet_blocks_0_attn_qkv.lokr_w1'\n// after: one file per format, single weight key per module\n'lora_unet_blocks_0_attn_qkv.lora_down'","handlingStrategy":"validation","validationCode":"seen = set()\nfor key in state_dict:\n    # apply your own normalization matching kohya->diffusers mapping\n    norm = key.replace('lora_unet_', '').replace('lora_te_', '')\n    if norm in seen:\n        raise ValueError(f'kohya keys collide after normalization: {norm}')\n    seen.add(norm)","typeGuard":"def is_pure_kohya_layout(state_dict: dict[str, object]) -> bool:\n    return all(isinstance(k, str) and (k.startswith('lora_unet_') or k.startswith('lora_te_')) for k in state_dict)","tryCatchPattern":"try:\n    model = lora_model_from_krea2_state_dict(state_dict)\nexcept ValueError as e:\n    if 'conflicting layers' in str(e) and 'from' in str(e):\n        logger.error('Kohya LoRA collision: %s', e)\n        # drop the duplicate entry named after 'and' in the message\n    else:\n        raise","preventionTips":["Do not mix plain Kohya LoRA tensors with LyCORIS tensors for the same modules in one file.","Verify one weight entry per module before loading.","Load LyCORIS files with a LyCORIS-aware loader instead."],"tags":["lora","kohya","key-collision","krea2"],"backgroundTag":"duplicate-key-collision","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}