invoke-ai/InvokeAI · warning · NotAMatchError

expected a .safetensors file, got {mod.path.suffix or '(no s

Error message

expected a .safetensors file, got {mod.path.suffix or '(no suffix)'}

What it means

`NotAMatchError` from the single-file branch of `QwenVLTextEncoderConfig.from_model_on_disk`: the candidate file is not a `.safetensors` file, so the loader rejects it before reading any keys. Only safetensors checkpoints are supported for single-file Qwen VL encoders; other extensions (`.bin`, `.pt`, `.ckpt`, no suffix) cannot be inspected cheaply or safely.

Source

Thrown at invokeai/backend/model_manager/configs/qwen_vl_encoder.py:142

    The matching tokenizer + processor are pulled from HuggingFace
    (`Qwen/Qwen2.5-VL-7B-Instruct`) on first use and cached for offline use.
    """

    base: Literal[BaseModelType.Any] = Field(default=BaseModelType.Any)
    type: Literal[ModelType.QwenVLEncoder] = Field(default=ModelType.QwenVLEncoder)
    format: Literal[ModelFormat.Checkpoint] = Field(default=ModelFormat.Checkpoint)

    @classmethod
    def from_model_on_disk(cls, mod: ModelOnDisk, override_fields: dict[str, Any]) -> Self:
        raise_if_not_file(mod)

        raise_for_override_fields(cls, override_fields)

        # Only safetensors checkpoints are supported as single-file Qwen VL encoders.
        # Reject other extensions cheaply before attempting to read keys.
        if mod.path.suffix != ".safetensors":
            raise NotAMatchError(f"expected a .safetensors file, got {mod.path.suffix or '(no suffix)'}")

        # Read only the key index — a 7GB fp8 encoder weighs ~7GB on disk, but we
        # only need the key names to classify it, not the tensor data.
        try:
            keys = _read_safetensors_keys(mod.path)
        except Exception as e:
            raise NotAMatchError(f"could not read safetensors header: {e}") from e

        if not _has_qwen_vl_keys(keys):
            raise NotAMatchError("state dict does not look like a Qwen2.5-VL/Qwen2-VL checkpoint")

        return cls(**override_fields)

View on GitHub (pinned to 0b6a024f2f)

Solutions

  1. Convert the checkpoint to safetensors (e.g. via `safetensors.torch.save_file` or a conversion script) and install the `.safetensors` file
  2. Download the safetensors variant from the model repo instead of the `.bin` variant
  3. Ensure the file keeps its `.safetensors` extension (don't strip it when renaming)
  4. If the path is actually a directory-based model, let the folder-branch of the config handle it instead of pointing at a loose file

Example fix

// before
mv model.bin qwen_encoder.safetensors   # wrong: just renaming
// after
python -c "from safetensors.torch import load_file,save_file; ..."  # actually convert, keep .safetensors
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import Path

def is_safetensors_file(path: Path) -> bool:
    return path.is_file() and path.suffix == ".safetensors"

Type guard

def is_single_file_safetensors(mod_path: Path) -> bool:
    return mod_path.is_file() and mod_path.suffix == ".safetensors"

Try / catch

try:
    cfg = QwenVLTextEncoderConfig.from_model_on_disk(mod, override_fields)
except NotAMatchError as e:
    if "expected a .safetensors file" in str(e):
        print("Convert or re-download the checkpoint in safetensors format")
    raise

Prevention

When it happens

Trigger: Installing a single-file Qwen VL encoder whose `ModelOnDisk.path` suffix is not `.safetensors` — e.g. a PyTorch `.bin`/`.pt` checkpoint, an archive, or a directory-less file with no extension.

Common situations: Old-style torch pickle checkpoints, config files placed at the model root and probed as weights, renamed downloads that lost the extension, GGUF or fp8 files with custom extensions.

Related errors


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