{"record":{"id":"89978f43b446ce34","repo":"invoke-ai/InvokeAI","slug":"text-encoder-class-is-sorted-candidates-or-unkn","errorCode":null,"errorMessage":"text_encoder class is {sorted(candidates) or 'unknown'}, expected one of {sorted(_RECOGNIZED_TEXT_ENCODER_CLASSES)}","messagePattern":"text_encoder class is (.+?), expected one of (.+?)","errorType":"validation","errorClass":"NotAMatchError","httpStatus":null,"severity":"error","filePath":"invokeai/backend/model_manager/configs/qwen_vl_encoder.py","lineNumber":109,"sourceCode":"        if not tokenizer_dir.is_dir():\n            raise NotAMatchError(\"missing tokenizer/ subfolder\")\n\n        config_path = text_encoder_dir / \"config.json\"\n        if not config_path.is_file():\n            raise NotAMatchError(f\"missing {config_path}\")\n\n        try:\n            with open(config_path, \"r\", encoding=\"utf-8\") as f:\n                cfg = json.load(f)\n        except (OSError, json.JSONDecodeError) as e:\n            raise NotAMatchError(f\"could not read text_encoder/config.json: {e}\") from e\n\n        class_name = cfg.get(\"_class_name\")\n        architectures = cfg.get(\"architectures\") or []\n        candidates = {class_name, *architectures} - {None}\n\n        if not candidates & _RECOGNIZED_TEXT_ENCODER_CLASSES:\n            raise NotAMatchError(\n                f\"text_encoder class is {sorted(candidates) or 'unknown'}, \"\n                f\"expected one of {sorted(_RECOGNIZED_TEXT_ENCODER_CLASSES)}\"\n            )\n\n        return cls(**override_fields)\n\n\nclass QwenVLEncoder_Checkpoint_Config(Checkpoint_Config_Base, Config_Base):\n    \"\"\"Configuration for single-file Qwen2.5-VL encoder checkpoints (safetensors).\n\n    This matches ComfyUI-style consolidated single-file encoders such as\n    `qwen_2.5_vl_7b_fp8_scaled.safetensors`, which bundle the language model\n    and the visual tower into one file (typically with FP8 + per-tensor\n    `weight_scale` ComfyUI quantization).\n\n    The matching tokenizer + processor are pulled from HuggingFace\n    (`Qwen/Qwen2.5-VL-7B-Instruct`) on first use and cached for offline use.\n    \"\"\"","sourceCodeStart":91,"sourceCodeEnd":127,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/backend/model_manager/configs/qwen_vl_encoder.py#L91-L127","documentation":"`NotAMatchError` raised when `text_encoder/config.json` parses but its `_class_name` / `architectures` do not intersect `_RECOGNIZED_TEXT_ENCODER_CLASSES` — i.e. the folder holds a text encoder InvokeAI does not classify as a Qwen2.5-VL/Qwen2-VL encoder (e.g. T5, CLIP, or an unknown class). The message lists the found candidates and the accepted set.","triggerScenarios":"Pointing the installer at a multi-model dump where `text_encoder/` belongs to a different architecture; a HF repo changed `_class_name` across versions; a custom or renamed encoder class in config.json.","commonSituations":"Mixing components from different checkpoints (e.g. SDXL's text_encoder dropped into a Qwen VL folder), renamed classes in newer transformers versions, fine-tune repos that override `architectures`, or manually edited config.json.","solutions":["Open `text_encoder/config.json` and check `_class_name` / `architectures`; they must be a recognized Qwen2-VL/Qwen2.5-VL text encoder class","Replace `text_encoder/` with the folder from an official Qwen2.5-VL/Qwen2-VL release","If classes were renamed by a library update, refresh config.json from the upstream repo rather than hand-editing","Confirm you are installing the right model type — non-Qwen encoders will never match this config"],"exampleFix":"// before: text_encoder/config.json\n{\"_class_name\": \"CLIPTextModel\", ...}\n// after\n{\"_class_name\": \"Qwen2VLForConditionalGeneration\", \"architectures\": [\"Qwen2VLForConditionalGeneration\"], ...}","handlingStrategy":"validation","validationCode":"import json\nfrom pathlib import Path\n\nEXPECTED = {\"Qwen2VLForConditionalGeneration\", \"Qwen2_5_VLForConditionalGeneration\"}  # check _RECOGNIZED_TEXT_ENCODER_CLASSES\n\ndef is_recognized_encoder(model_dir: Path) -> bool:\n    cfg = json.loads((model_dir / \"text_encoder\" / \"config.json\").read_text())\n    cands = {cfg.get(\"_class_name\"), *(cfg.get(\"architectures\") or [])} - {None}\n    return bool(cands & EXPECTED)","typeGuard":null,"tryCatchPattern":"try:\n    cfg = QwenVLTextEncoderConfig.from_model_on_disk(mod, override_fields)\nexcept NotAMatchError as e:\n    print(e)  # lists found classes vs expected; swap in correct text_encoder/ folder\n    raise","preventionTips":["Keep component folders from the same parent checkpoint together — never mix text encoders across models","Check `_class_name` in config.json before installing custom merges","If a library update renamed classes, refresh config.json from upstream"],"tags":["qwen-vl","model-mismatch","config"],"backgroundTag":"model-architecture-mismatch","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}