invoke-ai/InvokeAI · info · NotAMatchError

state dict looks like a T5 encoder (has 'enc.blk.*' keys)…

Error message

state dict looks like a T5 encoder (has 'enc.blk.*' keys), not a Qwen3 encoder

What it means

NotAMatchError raised by Qwen3Encoder._validate_looks_like_qwen3_model (qwen3_encoder.py:237). The state dict matches Qwen3's shared keys (token_embd.weight) but also carries 'enc.blk.*' keys, which identify a T5 encoder. Qwen3 encoders never use the enc. prefix, so this config rejects the model so it can be classified as T5Encoder instead.

Solutions

  1. Nothing is wrong with the file per se — let the scan continue; InvokeAI should classify it as T5Encoder automatically.
  2. If it is misclassified afterward, install it explicitly as a T5Encoder/CLIPEmbedder-style model rather than Qwen3Encoder.
  3. Confirm the GGUF is genuinely T5; if it was converted wrongly from a Qwen3 model, re-convert with a current converter so keys use blk.* without enc.*.
  4. Exclude the T5 encoder from the directory being scanned as a Qwen3 encoder.

Example fix

// before
install(models/, 't5-encoder.gguf')  # scanned as Qwen3Encoder candidate
// after
install_as(models/, 't5-encoder.gguf', model_type='T5Encoder')
Defensive patterns

Strategy: validation

Validate before calling

def is_t5_gguf(state_dict: dict) -> bool:
    return any(k.startswith('enc.blk.') for k in state_dict)  # if True, install as T5Encoder, not Qwen3Encoder

Type guard

def is_qwen3_not_t5(state_dict: dict) -> bool:
    keys = set(state_dict)
    return ('token_embd.weight' in keys or any(k.startswith('blk.') for k in keys)) and not any(k.startswith('enc.blk.') for k in keys)

Try / catch

try:
    register_model(path, model_type='Qwen3Encoder')
except NotAMatchError:
    register_model(path, model_type='T5Encoder')

Prevention

When it happens

Trigger: from_model_on_disk identification of a GGUF whose tensors include enc.blk.* (a T5-family text encoder GGUF) while the Qwen3Encoder config heuristic runs.

Common situations: Installing a T5 / FLUX T5-Encoder / UM-T5 GGUF converted with llama.cpp; older T5 GGUFs that predate dedicated T5Encoder config matching; re-identifying a previously mislabeled model so the Qwen3 config probes it first.

Related errors


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

Appendix: source

Thrown at invokeai/backend/model_manager/configs/qwen3_encoder.py:237

        We previously defaulted to 4B for unknown sizes, but that swallowed other causal-LM GGUFs
        (Mistral, Llama, ...) which share llama.cpp tensor naming with Qwen3.
        """
        state_dict = mod.load_state_dict()
        variant = _get_qwen3_variant_from_state_dict(state_dict)
        if variant is None:
            raise NotAMatchError("hidden size does not match a known Qwen3 variant")
        return variant

    @classmethod
    def _validate_looks_like_qwen3_model(cls, mod: ModelOnDisk) -> None:
        state_dict = mod.load_state_dict()
        if not _has_qwen3_keys(state_dict):
            raise NotAMatchError("state dict does not look like a Qwen3 model")
        # Reject T5 encoders: they share the token_embd.weight key with Qwen3 GGUFs but use the ``enc.``
        # block prefix, and must be classified as T5Encoder (Qwen3 encoders never have ``enc.blk.*`` keys).
        if _has_t5_encoder_keys(state_dict):
            raise NotAMatchError("state dict looks like a T5 encoder (has 'enc.blk.*' keys), not a Qwen3 encoder")
        # Reject Gemma-2/3 encoders: their GGUFs also carry token_embd.weight + blk.* keys but use
        # post-attention / post-feedforward norms a Qwen3 encoder never has; they must be classified as
        # Gemma2Encoder (otherwise a Gemma GGUF matches both configs and can be re-identified wrongly).
        if _has_gemma2_keys(state_dict):
            raise NotAMatchError(
                "state dict looks like a Gemma-2 encoder (has post_attention_norm/post_ffw_norm keys), "
                "not a Qwen3 encoder"
            )
        # Reject Qwen2.5-VL / Qwen2-VL encoders: they carry a visual tower and must be
        # classified as QwenVLEncoder (text-only Qwen3 encoders never have one).
        if _has_qwen_vl_visual_tower(state_dict):
            raise NotAMatchError(
                "state dict bundles a Qwen-VL visual tower; this is a Qwen-VL encoder, not a text-only Qwen3 encoder"
            )

    @classmethod
    def _validate_does_not_look_like_gguf_quantized(cls, mod: ModelOnDisk) -> None:
        has_ggml = _has_ggml_tensors(mod.load_state_dict())

View on GitHub (pinned to 0b6a024f2f)