invoke-ai/InvokeAI · error · NotAMatchError
model does not match Z-Image LoRA heuristics
Error message
model does not match Z-Image LoRA heuristics
What it means
NotAMatchError raised by LoRA_LyCORIS_ZImage_Config._validate_looks_like_lora when the file neither matches the Z-Image Kohya LoRA detector (is_state_dict_likely_z_image_kohya_lora) nor has both Z-Image-style key prefixes (diffusion_model.layers., diffusion_model.context_refiner., diffusion_model.noise_refiner., transformer.layers., base_model.model.transformer.layers.) and LoRA weight suffixes (lora_A/lora_B/lora_down/lora_up/dora_scale). The config class requires both signals to claim a file as a Z-Image LoRA.
Source
Thrown at invokeai/backend/model_manager/configs/lora.py:763
},
)
# Also check for LoRA weight suffixes (various formats)
has_lora_suffix = state_dict_has_any_keys_ending_with(
state_dict,
{
"lora_A.weight",
"lora_B.weight",
"lora_down.weight",
"lora_up.weight",
"dora_scale",
},
)
if has_z_image_lora_keys and has_lora_suffix:
return
raise NotAMatchError("model does not match Z-Image LoRA heuristics")
@classmethod
def _get_base_or_raise(cls, mod: ModelOnDisk) -> BaseModelType:
"""Z-Image LoRAs are identified by their diffusion_model.layers structure.
Z-Image uses S3-DiT architecture with layer names like:
- diffusion_model.layers.0.attention.to_k.lora_A.weight
- diffusion_model.layers.0.feed_forward.w1.lora_A.weight
- lora_unet__layers_0_attention_to_k.lora_down.weight (Kohya format)
"""
from invokeai.backend.patches.lora_conversions.z_image_lora_conversion_utils import (
is_state_dict_likely_z_image_kohya_lora,
)
state_dict = mod.load_state_dict()
# Check for Kohya format
if is_state_dict_likely_z_image_kohya_lora(state_dict):View on GitHub (pinned to 0b6a024f2f)
Solutions
- Confirm the file is actually a Z-Image LoRA; if it is for another base (Flux/Qwen/etc.), no action needed — another config should match it.
- Update InvokeAI — key-pattern heuristics for Z-Image trainers expand over time.
- Re-export the LoRA in Kohya format (lora_unet__layers_X_attention_to_k.lora_down.weight naming) or diffusers PEFT format so it matches known patterns.
- If keys use a variant prefix, rename keys in the state dict to one of the recognized prefixes (diffusion_model.layers., transformer.layers., etc.) before import.
- Use explicit base-model override fields at install time to bypass heuristic matching.
Example fix
// before: Z-Image LoRA with custom prefix 'net.layers.0.attn.to_k.lora_A.weight'
// after: rewrite keys to the recognized S3-DiT pattern
sd = {k.replace("net.layers.", "diffusion_model.layers."): v for k, v in sd.items()}
save_file(sd, "model.safetensors") Defensive patterns
Strategy: validation
Validate before calling
from invokeai.backend.patches.lora_conversions.z_image_lora_conversion_utils import is_state_dict_likely_z_image_kohya_lora
sd = load_file("model.safetensors")
prefixes = ("diffusion_model.layers.", "diffusion_model.context_refiner.",
"diffusion_model.noise_refiner.", "transformer.layers.",
"base_model.model.transformer.layers.")
suffixes = ("lora_A.weight", "lora_B.weight", "lora_down.weight", "lora_up.weight", "dora_scale")
ok = is_state_dict_likely_z_image_kohya_lora(sd) or (
any(k.startswith(prefixes) for k in sd) and any(k.endswith(suffixes) for k in sd)
)
if not ok:
print("Not a recognizable Z-Image LoRA") Type guard
def is_z_image_lora_state_dict(state_dict: dict) -> bool:
prefixes = ("diffusion_model.layers.", "transformer.layers.", "base_model.model.transformer.layers.")
suffixes = ("lora_A.weight", "lora_B.weight", "lora_down.weight", "lora_up.weight", "dora_scale")
return any(k.startswith(prefixes) for k in state_dict) and any(k.endswith(suffixes) for k in state_dict) Try / catch
try:
config = LoRA_LyCORIS_ZImage_Config.from_model_on_disk(mod, {})
except NotAMatchError as e:
logger.warning("Not a Z-Image LoRA (%s); trying other LoRA configs", e)
config = LoRA_LyCORIS_Config_Base.from_model_on_disk(mod, {}) Prevention
- Only feed files to the Z-Image config that actually target Z-Image's S3-DiT (diffusion_model.layers.X) structure.
- Re-export custom-trainer LoRAs in Kohya or PEFT naming before import.
- Inspect key prefixes with safetensors before importing; unknown DiT families will fail these heuristics.
- Update InvokeAI when new trainer naming variants appear.
When it happens
Trigger: from_model_on_disk probes a candidate against the Z-Image LyCORIS config and the state dict lacks the diffusion_model.layers.X structure (Z-Image S3-DiT) or lacks any recognizable LoRA weight suffix — e.g. a non-LoRA checkpoint, or a LoRA for another DiT model whose keys don't start with the expected prefixes.
Common situations: Scanning a regular diffusion checkpoint that happens to contain LoRA-ish keys, importing a LoRA for a similar architecture (Flux, Qwen-Image, Chroma) that routes through the Z-Image validator, or a Z-Image LoRA saved with fully custom key names by an unlisted trainer.
Related errors
- model does not match Qwen Image LoRA heuristics
- unrecognized token vector length {token_vector_length}
- model is not a FLUX.2 LoRA
- model does not look like a Z-Image LoRA
- LoRA "{lora_key}" already applied to transformer.
AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29).
Data as JSON: /api/errors/ffde53fc2102a292.
Report an issue: GitHub.