{"record":{"id":"f7a3d34cb6504796","repo":"invoke-ai/InvokeAI","slug":"state-dict-looks-like-a-gemma-2-encoder-has-post","errorCode":null,"errorMessage":"state dict looks like a Gemma-2 encoder (has post_attention_norm/post_ffw_norm keys), not a Qwen3 encoder","messagePattern":"state dict looks like a Gemma-2 encoder \\(has post_attention_norm/post_ffw_norm keys\\), not a Qwen3 encoder","errorType":"exception","errorClass":"NotAMatchError","httpStatus":null,"severity":"info","filePath":"invokeai/backend/model_manager/configs/qwen3_encoder.py","lineNumber":242,"sourceCode":"        variant = _get_qwen3_variant_from_state_dict(state_dict)\n        if variant is None:\n            raise NotAMatchError(\"hidden size does not match a known Qwen3 variant\")\n        return variant\n\n    @classmethod\n    def _validate_looks_like_qwen3_model(cls, mod: ModelOnDisk) -> None:\n        state_dict = mod.load_state_dict()\n        if not _has_qwen3_keys(state_dict):\n            raise NotAMatchError(\"state dict does not look like a Qwen3 model\")\n        # Reject T5 encoders: they share the token_embd.weight key with Qwen3 GGUFs but use the ``enc.``\n        # block prefix, and must be classified as T5Encoder (Qwen3 encoders never have ``enc.blk.*`` keys).\n        if _has_t5_encoder_keys(state_dict):\n            raise NotAMatchError(\"state dict looks like a T5 encoder (has 'enc.blk.*' keys), not a Qwen3 encoder\")\n        # Reject Gemma-2/3 encoders: their GGUFs also carry token_embd.weight + blk.* keys but use\n        # post-attention / post-feedforward norms a Qwen3 encoder never has; they must be classified as\n        # Gemma2Encoder (otherwise a Gemma GGUF matches both configs and can be re-identified wrongly).\n        if _has_gemma2_keys(state_dict):\n            raise NotAMatchError(\n                \"state dict looks like a Gemma-2 encoder (has post_attention_norm/post_ffw_norm keys), \"\n                \"not a Qwen3 encoder\"\n            )\n        # Reject Qwen2.5-VL / Qwen2-VL encoders: they carry a visual tower and must be\n        # classified as QwenVLEncoder (text-only Qwen3 encoders never have one).\n        if _has_qwen_vl_visual_tower(state_dict):\n            raise NotAMatchError(\n                \"state dict bundles a Qwen-VL visual tower; this is a Qwen-VL encoder, not a text-only Qwen3 encoder\"\n            )\n\n    @classmethod\n    def _validate_does_not_look_like_gguf_quantized(cls, mod: ModelOnDisk) -> None:\n        has_ggml = _has_ggml_tensors(mod.load_state_dict())\n        if has_ggml:\n            raise NotAMatchError(\"state dict looks like GGUF quantized\")\n\n\n# Transformers architectures the unquantized Qwen3 encoder config accepts.","sourceCodeStart":224,"sourceCodeEnd":260,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/backend/model_manager/configs/qwen3_encoder.py#L224-L260","documentation":"NotAMatchError raised by Qwen3Encoder._validate_looks_like_qwen3_model (qwen3_encoder.py:242). Gemma-2/3 GGUF encoders share token_embd.weight + blk.* keys with Qwen3 but additionally have post_attention_norm/post_ffw_norm tensors, which Qwen3 never has. The config raises so the model is classified as Gemma2Encoder instead of being wrongly re-identified as a Qwen3 encoder.","triggerScenarios":"from_model_on_disk identification of a Gemma-2/Gemma-3 text-encoder GGUF whose state dict contains post_attention_norm/post_ffw_norm keys while the Qwen3Encoder config probes it.","commonSituations":"Installing a Gemma 2 / Gemma 3 GGUF text encoder (e.g. for FLUX or other pipelines) into InvokeAI; key-collision between llama.cpp tensor naming conventions across Gemma and Qwen3.","solutions":["Expected behavior during disambiguation — allow the scan to continue so Gemma2Encoder matches.","If the model ends up unidentified, install it explicitly as a Gemma2Encoder model.","Verify the GGUF is truly Gemma (check metadata/general.architecture = gemma); if it's actually Qwen3 with stray keys, re-convert it.","Keep the Gemma encoder in its own folder so it is not probed as a Qwen3 encoder candidate."],"exampleFix":"// before\nmodels/encoders/gemma-3-encoder.gguf  // inside qwen3 scan path\n// after\nmodels/encoders/gemma-3-encoder.gguf installed as Gemma2Encoder (or moved out of the Qwen3 encoder folder)","handlingStrategy":"validation","validationCode":"def is_gemma_encoder(state_dict: dict) -> bool:\n    keys = set(state_dict)\n    return any('post_attention_norm' in k or 'post_ffw_norm' in k for k in keys)  # install as Gemma2Encoder","typeGuard":"def is_qwen3_not_gemma(state_dict: dict) -> bool:\n    keys = set(state_dict)\n    has_norm_keys = any('post_attention_norm' in k or 'post_ffw_norm' in k for k in keys)\n    return (any(k.startswith('blk.') for k in keys) or 'token_embd.weight' in keys) and not has_norm_keys","tryCatchPattern":"try:\n    register_model(path, model_type='Qwen3Encoder')\nexcept NotAMatchError:\n    register_model(path, model_type='Gemma2Encoder')","preventionTips":["Check general.architecture GGUF metadata (gemma vs qwen3) before importing.","Install Gemma GGUF encoders explicitly as Gemma2Encoder.","Scan model families from separate directories to avoid cross-config probing."],"tags":["model-identification","gguf","gemma","qwen3"],"backgroundTag":"model-not-a-match","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}