{"record":{"id":"ffde53fc2102a292","repo":"invoke-ai/InvokeAI","slug":"model-does-not-match-z-image-lora-heuristics","errorCode":null,"errorMessage":"model does not match Z-Image LoRA heuristics","messagePattern":"model does not match Z-Image LoRA heuristics","errorType":"exception","errorClass":"NotAMatchError","httpStatus":null,"severity":"error","filePath":"invokeai/backend/model_manager/configs/lora.py","lineNumber":763,"sourceCode":"            },\n        )\n\n        # Also check for LoRA weight suffixes (various formats)\n        has_lora_suffix = state_dict_has_any_keys_ending_with(\n            state_dict,\n            {\n                \"lora_A.weight\",\n                \"lora_B.weight\",\n                \"lora_down.weight\",\n                \"lora_up.weight\",\n                \"dora_scale\",\n            },\n        )\n\n        if has_z_image_lora_keys and has_lora_suffix:\n            return\n\n        raise NotAMatchError(\"model does not match Z-Image LoRA heuristics\")\n\n    @classmethod\n    def _get_base_or_raise(cls, mod: ModelOnDisk) -> BaseModelType:\n        \"\"\"Z-Image LoRAs are identified by their diffusion_model.layers structure.\n\n        Z-Image uses S3-DiT architecture with layer names like:\n        - diffusion_model.layers.0.attention.to_k.lora_A.weight\n        - diffusion_model.layers.0.feed_forward.w1.lora_A.weight\n        - lora_unet__layers_0_attention_to_k.lora_down.weight (Kohya format)\n        \"\"\"\n        from invokeai.backend.patches.lora_conversions.z_image_lora_conversion_utils import (\n            is_state_dict_likely_z_image_kohya_lora,\n        )\n\n        state_dict = mod.load_state_dict()\n\n        # Check for Kohya format\n        if is_state_dict_likely_z_image_kohya_lora(state_dict):","sourceCodeStart":745,"sourceCodeEnd":781,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/backend/model_manager/configs/lora.py#L745-L781","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: Z-Image LoRA with custom prefix 'net.layers.0.attn.to_k.lora_A.weight'\n// after: rewrite keys to the recognized S3-DiT pattern\nsd = {k.replace(\"net.layers.\", \"diffusion_model.layers.\"): v for k, v in sd.items()}\nsave_file(sd, \"model.safetensors\")","handlingStrategy":"validation","validationCode":"from invokeai.backend.patches.lora_conversions.z_image_lora_conversion_utils import is_state_dict_likely_z_image_kohya_lora\n\nsd = load_file(\"model.safetensors\")\nprefixes = (\"diffusion_model.layers.\", \"diffusion_model.context_refiner.\",\n            \"diffusion_model.noise_refiner.\", \"transformer.layers.\",\n            \"base_model.model.transformer.layers.\")\nsuffixes = (\"lora_A.weight\", \"lora_B.weight\", \"lora_down.weight\", \"lora_up.weight\", \"dora_scale\")\nok = is_state_dict_likely_z_image_kohya_lora(sd) or (\n    any(k.startswith(prefixes) for k in sd) and any(k.endswith(suffixes) for k in sd)\n)\nif not ok:\n    print(\"Not a recognizable Z-Image LoRA\")","typeGuard":"def is_z_image_lora_state_dict(state_dict: dict) -> bool:\n    prefixes = (\"diffusion_model.layers.\", \"transformer.layers.\", \"base_model.model.transformer.layers.\")\n    suffixes = (\"lora_A.weight\", \"lora_B.weight\", \"lora_down.weight\", \"lora_up.weight\", \"dora_scale\")\n    return any(k.startswith(prefixes) for k in state_dict) and any(k.endswith(suffixes) for k in state_dict)","tryCatchPattern":"try:\n    config = LoRA_LyCORIS_ZImage_Config.from_model_on_disk(mod, {})\nexcept NotAMatchError as e:\n    logger.warning(\"Not a Z-Image LoRA (%s); trying other LoRA configs\", e)\n    config = LoRA_LyCORIS_Config_Base.from_model_on_disk(mod, {})","preventionTips":["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."],"tags":["lora","z-image","model-import","heuristic-matching","invokeai"],"backgroundTag":"unrecognized-model-format","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}