invoke-ai/InvokeAI · error · ValueError
Krea-2 LoRA has conflicting layers that normalize to the sam
Error message
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. What it means
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.
Source
Thrown at invokeai/backend/patches/lora_conversions/krea2_lora_conversion_utils.py:232
converted_state_dict: Dict[str, torch.Tensor] = {}
source_keys: dict[str, str] = {}
for key, value in state_dict.items():
converted_key = key
if isinstance(key, str) and key.startswith(_KREA2_KOHYA_PREFIX):
# The flattened module path runs up to the first '.'; the weight suffix (``lora_down.weight``,
# ``alpha``, ...) follows it. Some writers emit a doubled separator after the prefix.
flat_path, dot, weight_suffix = key[len(_KREA2_KOHYA_PREFIX) :].lstrip("_").partition(".")
module_path = _unflatten_kohya_krea2_module_path(flat_path)
# Only rewrite when ``_group_by_layer`` can split the suffix back off. Un-flattening introduces
# dots into the module path, and the grouper's fallback for an unknown suffix is a blind
# ``rsplit(".", 2)`` — on a dotted path that cuts *inside the module name*, fusing two modules
# into one bogus layer that aborts the whole load. LyCORIS suffixes such as ``.lokr_w1`` or
# ``.hada_w1_a`` hit exactly that. Flattened, they have no interior dot and group harmlessly,
# so leaving them verbatim keeps them at the pre-existing warn-and-skip behaviour.
if module_path is not None and flat_path in fully_convertible_flat_paths:
converted_key = f"{module_path}{dot}{weight_suffix}"
if converted_key in converted_state_dict:
raise ValueError(
f"Krea-2 LoRA has conflicting layers that normalize to the same target '{converted_key}' "
f"(from '{source_keys[converted_key]}' and '{key}'). This mixed layout is unsupported - "
"refusing to silently drop one of the layers."
)
converted_state_dict[converted_key] = value
source_keys[converted_key] = str(key)
return converted_state_dict
def is_state_dict_likely_krea2_lora(state_dict: dict[str | int, torch.Tensor]) -> bool:
"""Checks if the provided state dict is likely a Krea-2 LoRA.
Requires the distinctive Krea-2 ``text_fusion`` / ``txtfusion`` / ``time_mod_proj`` modules so it does not
false-match Qwen-Image or Z-Image LoRAs that also carry ``transformer.transformer_blocks.`` keys.
"""
str_keys = [k for k in state_dict.keys() if isinstance(k, str)]
has_krea2_module = any(any(sig in k for sig in KREA2_TRANSFORMER_SIGNATURE_KEYS) for k in str_keys)
has_lora_suffix = any(View on GitHub (pinned to 0b6a024f2f)
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.
Example fix
// before (colliding keys in one file) 'lora_unet_blocks_0_attn_qkv.alpha' 'lora_unet_blocks_0_attn_qkv.lokr_w1' // after: one file per format, single weight key per module 'lora_unet_blocks_0_attn_qkv.lora_down'
Defensive patterns
Strategy: validation
Validate before calling
seen = set()
for key in state_dict:
# apply your own normalization matching kohya->diffusers mapping
norm = key.replace('lora_unet_', '').replace('lora_te_', '')
if norm in seen:
raise ValueError(f'kohya keys collide after normalization: {norm}')
seen.add(norm) Type guard
def is_pure_kohya_layout(state_dict: dict[str, object]) -> bool:
return all(isinstance(k, str) and (k.startswith('lora_unet_') or k.startswith('lora_te_')) for k in state_dict) Try / catch
try:
model = lora_model_from_krea2_state_dict(state_dict)
except ValueError as e:
if 'conflicting layers' in str(e) and 'from' in str(e):
logger.error('Kohya LoRA collision: %s', e)
# drop the duplicate entry named after 'and' in the message
else:
raise Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Krea-2 LoRA has conflicting layers that normalize to the sam
- Expected ModelPatchRaw for LoRA '{lora.lora.key}', got {type
- model does not match Krea-2 LoRA heuristics (no complete lor
- Krea-2 LoRA has an incomplete lora_A/B (or lora_down/up) wei
- model does not look like a Krea-2 LoRA
AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29).
Data as JSON: /api/errors/0a466f29fcb165cf.
Report an issue: GitHub.