invoke-ai/InvokeAI · error · NotAMatchError

Krea-2 requires a Qwen3-VL 4B checkpoint with hidden size {_

Error message

Krea-2 requires a Qwen3-VL 4B checkpoint with hidden size {_KREA2_QWEN3_VL_HIDDEN_SIZE}, got {hidden_size}

What it means

InvokeAI's Qwen3-VL encoder config (used by Krea-2) inspects the embedding weight tensor of a single-file .safetensors checkpoint and requires its second dimension (hidden size) to be exactly 2560 (the Qwen3-VL 4B architecture). This NotAMatchError is thrown when the embedding tensor is missing, malformed, or has a different hidden size, meaning the checkpoint is not a Qwen3-VL 4B model. It is a model-identification guard so incompatible weights are not silently registered as a Krea-2 text encoder.

Source

Thrown at invokeai/backend/model_manager/configs/qwen3_vl_encoder.py:79

            if not candidate.is_relative_to(root):
                return False
            referenced_files.add(candidate)
        return bool(referenced_files) and all(path.is_file() for path in referenced_files)
    return False


def _validate_krea2_qwen3_vl_checkpoint_shape(state_dict: dict[str | int, Any]) -> None:
    embed_keys = (
        "model.embed_tokens.weight",
        "model.language_model.embed_tokens.weight",
        "language_model.embed_tokens.weight",
        "embed_tokens.weight",
    )
    embed = next((state_dict[key] for key in embed_keys if key in state_dict), None)
    shape = getattr(embed, "shape", ())
    if len(shape) < 2 or shape[1] != _KREA2_QWEN3_VL_HIDDEN_SIZE:
        hidden_size = shape[1] if len(shape) >= 2 else None
        raise NotAMatchError(
            f"Krea-2 requires a Qwen3-VL 4B checkpoint with hidden size "
            f"{_KREA2_QWEN3_VL_HIDDEN_SIZE}, got {hidden_size}"
        )
    if not any(isinstance(key, str) and ".layers.35." in key for key in state_dict):
        raise NotAMatchError("Krea-2 requires a Qwen3-VL 4B checkpoint containing language-model layer 35")


class Qwen3VLEncoder_Qwen3VLEncoder_Config(Config_Base):
    """Configuration for standalone Qwen3-VL text encoder models (diffusers-like directory format).

    Used by Krea-2, whose text conditioning comes from a Qwen3-VL model (``Qwen3VLModel``). The model
    weights are expected either in a ``text_encoder`` subfolder of the model directory or directly at the
    root (standalone download). This is distinct from the text-only ``Qwen3Encoder`` (Z-Image / FLUX.2
    Klein) and the Qwen2.5-VL ``QwenVLEncoder`` (Qwen Image).
    """

    base: Literal[BaseModelType.Any] = Field(default=BaseModelType.Any)
    type: Literal[ModelType.Qwen3VLEncoder] = Field(default=ModelType.Qwen3VLEncoder)

View on GitHub (pinned to 0b6a024f2f)

Solutions

  1. Download the correct Qwen3-VL 4B checkpoint (e.g. Qwen/Qwen3-VL-4B-Instruct or the Krea-2-specified encoder) whose hidden_size is 2560.
  2. Verify the checkpoint is complete: re-download the .safetensors file and compare its size/hash against the source.
  3. Open the safetensors header and confirm model.embed_tokens.weight has shape [vocab_size, 2560]; if you converted the model yourself, redo the conversion without reshaping the embedding.
  4. If the file is genuinely a different architecture, do not register it as a Qwen3VLEncoder; import it under its proper model type instead.

Example fix

// before: wrong-size variant downloaded
models/qwen3vl/qwen_3vl_2b.safetensors   # hidden_size 2048 -> NotAMatchError
// after: Krea-2 requires the 4B checkpoint
models/qwen3vl/qwen_3vl_4b_instruct.safetensors  # embed_tokens.weight: [151936, 2560]
Defensive patterns

Strategy: validation

Validate before calling

from safetensors import safe_open

def validate_qwen3vl_4b_checkpoint(path: str) -> bool:
    with safe_open(path, framework="pt") as f:
        for key in ("model.embed_tokens.weight", "model.language_model.embed_tokens.weight",
                    "language_model.embed_tokens.weight", "embed_tokens.weight"):
            if key in f.keys():
                return f.get_slice(key).get_shape()[1] == 2560
        return False

Type guard

def is_qwen3vl_4b_state_dict(sd: dict) -> bool:
    embed = next((sd[k] for k in ("model.embed_tokens.weight", "embed_tokens.weight") if k in sd), None)
    shape = getattr(embed, "shape", ())
    return len(shape) >= 2 and shape[1] == 2560 and any(".layers.35." in k for k in sd)

Try / catch

from invokeai.backend.model_manager.configs.identification_utils import NotAMatchError

try:
    config = Qwen3VLEncoder_Checkpoint_Config.from_model_on_disk(mod, {})
except NotAMatchError:
    logger.warning("%s is not a Qwen3-VL 4B checkpoint (hidden_size must be 2560)", mod.path)

Prevention

When it happens

Trigger: Calling Qwen3VLEncoder_Checkpoint_Config.from_model_on_disk on a .safetensors file whose state dict passed the visual-tower heuristic but whose embed tensor (model.embed_tokens.weight and siblings) has shape[1] != 2560, is 1-dimensional, or is absent.

Common situations: Pointing InvokeAI at a Qwen3-VL model in a different size (e.g. 2B or 8B variant with hidden_size 2048/4096), a text-only Qwen3 encoder file mislabeled with a visual tower, a truncated or partially downloaded safetensors file, or a quantized/repacked checkpoint with renamed or reshaped embedding tensors.

Related errors


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