invoke-ai/InvokeAI · error · ValueError

Layer '{layer_name}' does not match the expected pattern for

Error message

Layer '{layer_name}' does not match the expected pattern for FLUX LoRA weights.

What it means

lora_model_from_flux_onetrainer_state_dict groups OneTrainer FLUX LoRA keys into transformer/CLIP/T5 by prefix (lora_unet_/lora_te1_/lora_te2_). A layer name with none of those prefixes raises ValueError with the same message as the Kohya path, since both share the grouping convention.

Source

Thrown at invokeai/backend/patches/lora_conversions/flux_onetrainer_lora_conversion_utils.py:81

    for key, value in state_dict.items():
        layer_name, param_name = key.split(".", 1)
        if layer_name not in grouped_state_dict:
            grouped_state_dict[layer_name] = {}
        grouped_state_dict[layer_name][param_name] = value

    # Split the grouped state dict into transformer, CLIP, and T5 state dicts.
    transformer_grouped_sd: dict[str, dict[str, torch.Tensor]] = {}
    clip_grouped_sd: dict[str, dict[str, torch.Tensor]] = {}
    t5_grouped_sd: dict[str, dict[str, torch.Tensor]] = {}
    for layer_name, layer_state_dict in grouped_state_dict.items():
        if layer_name.startswith("lora_transformer"):
            transformer_grouped_sd[layer_name] = layer_state_dict
        elif layer_name.startswith("lora_te1"):
            clip_grouped_sd[layer_name] = layer_state_dict
        elif layer_name.startswith("lora_te2"):
            t5_grouped_sd[layer_name] = layer_state_dict
        else:
            raise ValueError(f"Layer '{layer_name}' does not match the expected pattern for FLUX LoRA weights.")

    # Convert the state dicts to the InvokeAI format.
    clip_grouped_sd = _convert_flux_clip_kohya_state_dict_to_invoke_format(clip_grouped_sd)
    t5_grouped_sd = _convert_flux_t5_kohya_state_dict_to_invoke_format(t5_grouped_sd)

    # Create LoRA layers.
    layers: dict[str, BaseLayerPatch] = {}
    for model_prefix, grouped_sd in [
        # (FLUX_LORA_TRANSFORMER_PREFIX, transformer_grouped_sd),
        (FLUX_LORA_CLIP_PREFIX, clip_grouped_sd),
        (FLUX_LORA_T5_PREFIX, t5_grouped_sd),
    ]:
        for layer_key, layer_state_dict in grouped_sd.items():
            layers[model_prefix + layer_key] = any_lora_layer_from_state_dict(layer_state_dict)

    # Handle the transformer.
    transformer_layers = _convert_flux_transformer_onetrainer_state_dict_to_invoke_format(transformer_grouped_sd)
    layers.update(transformer_layers)

View on GitHub (pinned to 0b6a024f2f)

Solutions

  1. Check the layer_name prefix; use the converter matching the model family the LoRA was trained for.
  2. Filter out unexpected keys before calling the loader.
  3. Update to an InvokeAI version that supports the new OneTrainer prefix, or strip/rename keys accordingly.
Defensive patterns

Strategy: validation

Validate before calling

bad = [k for k in state_dict if not k.startswith(("lora_unet_", "lora_te1_", "lora_te2_"))]
assert not bad, f"keys outside OneTrainer FLUX convention: {bad[:5]}"

Type guard

def is_flux_onetrainer_key(k: str) -> bool:
    return k.startswith(("lora_unet_", "lora_te1_", "lora_te2_"))

Try / catch

try:
    lora = lora_model_from_flux_onetrainer_state_dict(sd, model)
except ValueError as e:
    logger.error("OneTrainer FLUX LoRA unexpected layer: %s", e)
    lora = None

Prevention

When it happens

Trigger: Loading a OneTrainer FLUX LoRA whose top-level layer key has an unexpected prefix (SD-style 'lora_te', 'lora_unet' misspelled, or non-FLUX architecture keys).

Common situations: Loading an SD1.5/SDXL LoRA through the FLUX OneTrainer loader; OneTrainer version changes introducing new prefixes; stray keys (e.g. 'lora_prior') in the file.

Related errors


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