{"record":{"id":"d6a96bed317a13bf","repo":"invoke-ai/InvokeAI","slug":"expected-a-safetensors-file-got-mod-path-suffix-d6a96b","errorCode":null,"errorMessage":"expected a .safetensors file, got {mod.path.suffix or '(no suffix)'}","messagePattern":"expected a \\.safetensors file, got (.+?)","errorType":"validation","errorClass":"NotAMatchError","httpStatus":null,"severity":"error","filePath":"invokeai/backend/model_manager/configs/qwen3_vl_encoder.py","lineNumber":188,"sourceCode":"\n    Distinguished from the text-only ``Qwen3Encoder`` checkpoint (Z-Image) by the presence of the\n    Qwen3-VL visual tower. The tokenizer is not bundled in single-file checkpoints and is pulled from\n    HuggingFace (``Qwen/Qwen3-VL-4B-Instruct``) by the loader.\n    \"\"\"\n\n    base: Literal[BaseModelType.Any] = Field(default=BaseModelType.Any)\n    type: Literal[ModelType.Qwen3VLEncoder] = Field(default=ModelType.Qwen3VLEncoder)\n    format: Literal[ModelFormat.Checkpoint] = Field(default=ModelFormat.Checkpoint)\n    cpu_only: bool | None = Field(default=None, description=\"Whether this model should run on CPU only\")\n\n    @classmethod\n    def from_model_on_disk(cls, mod: ModelOnDisk, override_fields: dict[str, Any]) -> Self:\n        raise_if_not_file(mod)\n\n        raise_for_override_fields(cls, override_fields)\n\n        if mod.path.suffix.lower() != \".safetensors\":\n            raise NotAMatchError(f\"expected a .safetensors file, got {mod.path.suffix or '(no suffix)'}\")\n\n        state_dict = mod.load_state_dict()\n        if not _is_qwen3_vl_encoder_state_dict(state_dict):\n            raise NotAMatchError(\"state dict does not look like a single-file Qwen3-VL encoder\")\n        _validate_krea2_qwen3_vl_checkpoint_shape(state_dict)\n\n        return cls(**override_fields)\n","sourceCodeStart":170,"sourceCodeEnd":196,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/backend/model_manager/configs/qwen3_vl_encoder.py#L170-L196","documentation":"Raised as a NotAMatchError by Qwen3VLEncoder_Checkpoint_Config.from_model_on_disk when model identification is asked to classify a single-file model whose extension is not .safetensors. This config class only supports single-file Qwen3-VL encoder checkpoints in safetensors format; anything else (a .bin, .gguf, or a file with no extension) cannot be matched and the identifier moves on.","triggerScenarios":"Running model import/probe on a single file whose mod.path.suffix.lower() != '.safetensors' — e.g. a .pth/.bin PyTorch checkpoint, .gguf quantized file, .ckpt, or an extension-less file — with the Qwen3-VL checkpoint config in the matching candidate list.","commonSituations":"Downloading a ComfyUI-style encoder in .gguf or fp16 .bin form; renaming a file and losing the extension; older PyTorch checkpoints saved as pytorch_model.bin; confusing a directory-format model with the single-file format.","solutions":["Convert the checkpoint to safetensors (e.g. convert via safetensors.torch.save_file or a conversion script) and re-import.","Download the .safetensors variant of the encoder (ComfyUI qwen3vl_4b_* safetensors releases) instead of the .bin/.gguf one.","Restore the .safetensors extension if the file was renamed; verify with `ls`/`file` that it is actually a safetensors file.","Use the appropriate config class for the actual format (e.g. GGUF or diffusers-folder matchers) rather than this checkpoint matcher."],"exampleFix":"// before\nqwen_2.5_vl_7b.bin   -> import -> NotAMatchError\n\n// after\npython -c \"from safetensors.torch import load_file, save_file; import torch; sd=torch.load('qwen_2.5_vl_7b.bin',map_location='cpu'); save_file(sd,'qwen_2.5_vl_7b.safetensors')\"\nqwen_2.5_vl_7b.safetensors -> import -> matched","handlingStrategy":"validation","validationCode":"from pathlib import Path\n\ndef ensure_safetensors_file(path: Path) -> None:\n    if not path.is_file():\n        raise ValueError(f\"{path} is not a file\")\n    if path.suffix.lower() != \".safetensors\":\n        raise ValueError(f\"expected .safetensors, got {path.suffix or '(no suffix)'}\")","typeGuard":"from pathlib import Path\n\ndef is_safetensors_file(p: Path) -> bool:\n    return p.is_file() and p.suffix.lower() == \".safetensors\"","tryCatchPattern":"try:\n    invokeai_model_manager.probe(file_path)\nexcept NotAMatchError as e:\n    if str(e).startswith(\"expected a .safetensors file\"):\n        converted = convert_to_safetensors(file_path)  # e.g. .bin -> .safetensors\n        invokeai_model_manager.probe(converted)\n    else:\n        raise","preventionTips":["Prefer .safetensors releases from model hubs over .bin/.pth/.gguf variants.","Never rename checkpoints without preserving the extension; verify with `file` that the format matches.","Check the extension before adding a single-file model in InvokeAI.","Keep single-file checkpoints and diffusers folders in separate directories to avoid format confusion."],"tags":["invokeai","model-import","safetensors","file-format","not-a-match"],"backgroundTag":"unsupported-file-format","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}