{"record":{"id":"b1379ef4c9356a23","repo":"invoke-ai/InvokeAI","slug":"standalone-qwen3-vl-encoder-directory-does-not-con","errorCode":null,"errorMessage":"standalone Qwen3-VL encoder directory does not contain model weights","messagePattern":"standalone Qwen3-VL encoder directory does not contain model weights","errorType":"validation","errorClass":"NotAMatchError","httpStatus":null,"severity":"error","filePath":"invokeai/backend/model_manager/configs/qwen3_vl_encoder.py","lineNumber":149,"sourceCode":"                \"Qwen3VLModel\",\n                \"Qwen3VLForConditionalGeneration\",\n            },\n        )\n        _validate_krea2_qwen3_vl_config(expected_config_path)\n\n        if config_path_nested.exists():\n            weights_path = mod.path / \"text_encoder\"\n            tokenizer_path = mod.path / \"tokenizer\"\n        else:\n            weights_path = mod.path\n            tokenizer_path = mod.path\n\n        has_weights = _has_complete_pretrained_weights(weights_path)\n        has_tokenizer = (tokenizer_path / \"tokenizer.json\").exists() or (\n            (tokenizer_path / \"vocab.json\").exists() and (tokenizer_path / \"merges.txt\").exists()\n        )\n        if not has_weights:\n            raise NotAMatchError(\"standalone Qwen3-VL encoder directory does not contain model weights\")\n        if not has_tokenizer:\n            raise NotAMatchError(\"standalone Qwen3-VL encoder directory does not contain tokenizer files\")\n\n        return cls(**override_fields)\n\n\ndef _is_qwen3_vl_encoder_state_dict(state_dict: dict[str | int, Any]) -> bool:\n    \"\"\"True for a single-file Qwen3-VL encoder: a Qwen3 text decoder PLUS a visual tower.\n\n    The visual tower (``visual.*`` / ``model.visual.*``) distinguishes Qwen3-VL from the text-only\n    ``Qwen3Encoder`` (Z-Image / FLUX.2 Klein), which has ``model.layers.*`` but no visual tower.\n    \"\"\"\n    str_keys = [k for k in state_dict if isinstance(k, str)]\n    has_text_decoder = any(\".layers.\" in k and (\"model.\" in k or k.startswith(\"layers.\")) for k in str_keys)\n    has_visual_tower = any(k.startswith((\"visual.\", \"model.visual.\")) or \".visual.\" in k for k in str_keys)\n    return has_text_decoder and has_visual_tower\n\n","sourceCodeStart":131,"sourceCodeEnd":167,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/backend/model_manager/configs/qwen3_vl_encoder.py#L131-L167","documentation":"After confirming the config is a valid Qwen3-VL 4B config, from_model_on_disk verifies that the weights directory actually contains complete pretrained weights: a single model.safetensors or pytorch_model.bin, or a sharded index whose every referenced shard file exists and is inside the folder. If not, it throws this NotAMatchError because an encoder directory without usable weights cannot be registered.","triggerScenarios":"from_model_on_disk runs _has_complete_pretrained_weights on the weights path (text_encoder/ subfolder or directory root) and finds no model.safetensors/pytorch_model.bin and no valid complete sharded index - e.g. only an index json with missing shard files, or no weight files at all.","commonSituations":"Interrupted or partial HuggingFace download (index json present, shards missing), copying only config.json and tokenizer files, shards downloaded but renamed, shards placed outside the directory (absolute/escaping paths in weight_map), or storage cleanup deleting large safetensors shards.","solutions":["Re-download the model weights completely; for sharded models ensure every file listed in model.safetensors.index.json is present in the same folder.","Verify shard filenames in the index's weight_map match the files on disk exactly (no renaming or path prefixes).","If you assembled the folder by hand, copy the weight files (model.safetensors or pytorch_model.bin) next to config.json.","Use a resumable downloader (huggingface-cli download) to repair partial downloads, then rescan the folder in InvokeAI."],"exampleFix":"// before: sharded index with missing shard\nmodels/qwen3vl-encoder/\n  config.json\n  model.safetensors.index.json\n  (shards missing) -> NotAMatchError\n// after\nmodels/qwen3vl-encoder/\n  config.json\n  model.safetensors.index.json\n  model-00001-of-00002.safetensors\n  model-00002-of-00002.safetensors","handlingStrategy":"validation","validationCode":"import json\nfrom pathlib import Path\n\ndef has_complete_weights(model_dir: str) -> bool:\n    p = Path(model_dir) / \"text_encoder\"\n    if not p.is_dir():\n        p = Path(model_dir)\n    if (p / \"model.safetensors\").is_file() or (p / \"pytorch_model.bin\").is_file():\n        return True\n    for idx in (\"model.safetensors.index.json\", \"pytorch_model.bin.index.json\"):\n        ip = p / idx\n        if ip.is_file():\n            wm = json.loads(ip.read_text()).get(\"weight_map\", {})\n            if not all((p / fn).is_file() for fn in wm.values()):\n                return False\n            return bool(wm)\n    return False","typeGuard":"def weights_present(weights_dir) -> bool:\n    from pathlib import Path\n    p = Path(weights_dir)\n    return (p / \"model.safetensors\").is_file() or (p / \"pytorch_model.bin\").is_file() or (p / \"model.safetensors.index.json\").is_file()","tryCatchPattern":"try:\n    cfg = Qwen3VLEncoder_Qwen3VLEncoder_Config.from_model_on_disk(mod, {})\nexcept NotAMatchError as e:\n    if \"does not contain model weights\" in str(e):\n        logger.warning(\"%s has no complete weights; re-run huggingface-cli download\", mod.path)","preventionTips":["Use resumable downloaders (huggingface-cli download / snapshot_download) instead of manual per-file fetches.","For sharded models, verify every weight_map entry exists before importing.","Do not delete large safetensors shards to free space without removing the model from InvokeAI.","Keep shard files next to their index and unrenamed."],"tags":["model-import","missing-weights","invokeai","huggingface","partial-download"],"backgroundTag":"incomplete-model-download","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}