invoke-ai/InvokeAI · error · ValueError

Krea-2 LoRA has conflicting layers that normalize to the…

Error message

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.

What it means

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.

Solutions

  1. Strip one alias family from the file so each layer exists under only 'transformer.' or only 'diffusion_model.'.
  2. Re-export the LoRA from the trainer choosing a single prefix convention.
  3. If the two aliases carry different weights, decide which is correct and merge/drop the other explicitly before loading.

Example fix

// before
'transformer.blocks.0.attn.qkv.lora_down.weight': t1
'diffusion_model.blocks.0.attn.qkv.lora_down.weight': t2
// after: keep one alias only
'transformer.blocks.0.attn.qkv.lora_down.weight': t1
Defensive patterns

Strategy: validation

Validate before calling

def strip_alias(k: str) -> str:
    for p in ('transformer.', 'diffusion_model.'):
        if k.startswith(p):
            return k[len(p):]
    return k
bases = [strip_alias(k) for k in state_dict]
if len(bases) != len(set(bases)):
    raise ValueError('both transformer. and diffusion_model. aliases present')

Type guard

def uses_single_prefix(state_dict: dict[str, object]) -> bool:
    prefixes = {k.split('.', 1)[0] for k in state_dict if isinstance(k, str) and '.' in k}
    return prefixes <= {'transformer'} or prefixes <= {'diffusion_model'}

Try / catch

try:
    model = lora_model_from_krea2_state_dict(state_dict)
except ValueError as e:
    if 'transformer' in str(e) and 'diffusion_model' in str(e):
        logger.error('Mixed alias prefixes: %s', e)
        # normalize keys to one prefix and retry
    else:
        raise

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29). Data as JSON: /api/errors/905d0a9db09fe3ac. Report an issue: GitHub.

Appendix: source

Thrown at invokeai/backend/patches/lora_conversions/krea2_lora_conversion_utils.py:304

                clean_key = layer_key[len(prefix) :]
                is_text_encoder = True
                break
        if not is_text_encoder:
            for prefix in transformer_prefixes:
                if layer_key.startswith(prefix):
                    clean_key = layer_key[len(prefix) :]
                    break

        if is_text_encoder:
            final_key = f"{KREA2_LORA_QWEN3VL_PREFIX}{clean_key}"
        else:
            final_key = f"{KREA2_LORA_TRANSFORMER_PREFIX}{clean_key}"

        # The `transformer.` and `diffusion_model.` aliases normalize to the same target key. If two source
        # layers collide here, silently overwriting one would drop weights based on dict ordering, so reject
        # the mixed-layout adapter explicitly instead.
        if final_key in layers:
            raise ValueError(
                f"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."
            )
        layers[final_key] = any_lora_layer_from_state_dict(values)

    return ModelPatchRaw(layers=layers)


def _get_lora_layer_values(
    layer_key: str, layer_dict: dict[str, torch.Tensor], alpha: float | None
) -> dict[str, torch.Tensor]:
    """Convert PEFT (lora_A/lora_B) layer values to internal (lora_down/lora_up) format."""
    if "lora_A.weight" in layer_dict:
        if "lora_B.weight" not in layer_dict:
            raise ValueError(
                f"Malformed Krea-2 LoRA: layer '{layer_key}' has lora_A.weight but no matching lora_B.weight. "
                "The LoRA file is incomplete or corrupt."

View on GitHub (pinned to 0b6a024f2f)