{"record":{"id":"000521ce54c42e0f","repo":"invoke-ai/InvokeAI","slug":"directory-looks-like-a-full-diffusers-pipeline-ha-000521","errorCode":null,"errorMessage":"directory looks like a full diffusers pipeline (has model_index.json or transformer folder), not a standalone Qwen3-VL encoder","messagePattern":"directory looks like a full diffusers pipeline \\(has model_index\\.json or transformer folder\\), not a standalone Qwen3-VL encoder","errorType":"validation","errorClass":"NotAMatchError","httpStatus":null,"severity":"error","filePath":"invokeai/backend/model_manager/configs/qwen3_vl_encoder.py","lineNumber":111,"sourceCode":"    Klein) and the Qwen2.5-VL ``QwenVLEncoder`` (Qwen Image).\n    \"\"\"\n\n    base: Literal[BaseModelType.Any] = Field(default=BaseModelType.Any)\n    type: Literal[ModelType.Qwen3VLEncoder] = Field(default=ModelType.Qwen3VLEncoder)\n    format: Literal[ModelFormat.Qwen3VLEncoder] = Field(default=ModelFormat.Qwen3VLEncoder)\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_dir(mod)\n\n        raise_for_override_fields(cls, override_fields)\n\n        # Exclude full pipeline models - these should be matched as main models, not just encoders.\n        model_index_path = mod.path / \"model_index.json\"\n        transformer_path = mod.path / \"transformer\"\n        if model_index_path.exists() or transformer_path.exists():\n            raise NotAMatchError(\n                \"directory looks like a full diffusers pipeline (has model_index.json or transformer folder), \"\n                \"not a standalone Qwen3-VL encoder\"\n            )\n\n        # Support both a nested text_encoder/config.json and a standalone config.json at the root.\n        config_path_nested = mod.path / \"text_encoder\" / \"config.json\"\n        config_path_direct = mod.path / \"config.json\"\n\n        if config_path_nested.exists():\n            expected_config_path = config_path_nested\n        elif config_path_direct.exists():\n            expected_config_path = config_path_direct\n        else:\n            raise NotAMatchError(f\"unable to load config file: {config_path_nested} does not exist\")\n\n        # Qwen3-VL uses the Qwen3VLModel / Qwen3VLForConditionalGeneration architecture.\n        raise_for_class_name(\n            expected_config_path,","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/backend/model_manager/configs/qwen3_vl_encoder.py#L93-L129","documentation":"Qwen3VLEncoder_Qwen3VLEncoder_Config.from_model_on_disk scans a model directory and rejects it when it looks like a full diffusers pipeline (contains model_index.json or a transformer/ subfolder). Full pipelines must be registered as main models, not as a standalone text encoder, so InvokeAI throws this NotAMatchError to steer the import to the right model type.","triggerScenarios":"Calling from_model_on_disk (during model scan/import) on a directory that contains invokeai/backend/model_manager/configs/qwen3_vl_encoder.py-recognized layout markers model_index.json or transformer/ at its root, e.g. the full Krea-2 or Qwen3-VL diffusers repo checked out as one folder.","commonSituations":"Downloading an entire HuggingFace diffusers pipeline repo (with model_index.json, transformer/, text_encoder/, vae/, tokenizer/) and adding the whole folder as a text encoder; pointing the scan folder at a pipeline root instead of the text_encoder subfolder.","solutions":["Import the full pipeline directory as a main model instead of a text encoder, so InvokeAI splits it into components automatically.","Alternatively, add only the text_encoder subfolder (or a standalone directory containing config.json plus weights) as the Qwen3-VL encoder.","Remove or rename model_index.json / move the transformer/ folder out if you are assembling a custom standalone encoder directory."],"exampleFix":"// before: whole pipeline folder added as encoder\nmodels/krea2/           # contains model_index.json, transformer/, text_encoder/ -> NotAMatchError\n// after: add the encoder component only\nmodels/krea2-text-encoder/  # config.json + model.safetensors + tokenizer files","handlingStrategy":"validation","validationCode":"from pathlib import Path\n\ndef looks_like_full_pipeline(model_dir: str) -> bool:\n    p = Path(model_dir)\n    return (p / \"model_index.json\").exists() or (p / \"transformer\").is_dir()\n\n# Add models/encoder only if not looks_like_full_pipeline(...); otherwise import as a main model.","typeGuard":"def is_standalone_encoder_dir(p) -> bool:\n    from pathlib import Path\n    p = Path(p)\n    return p.is_dir() and not (p / \"model_index.json\").exists() and not (p / \"transformer\").is_dir()","tryCatchPattern":"try:\n    cfg = Qwen3VLEncoder_Qwen3VLEncoder_Config.from_model_on_disk(mod, {})\nexcept NotAMatchError as e:\n    if \"full diffusers pipeline\" in str(e):\n        logger.info(\"%s is a full pipeline; register it as a main model instead\", mod.path)","preventionTips":["Download HuggingFace repos selectively (text_encoder/ + tokenizer/ only) when you want a standalone encoder.","Never point InvokeAI's scan folder import at a repo root containing model_index.json for encoder registration.","Prefer importing the full pipeline once and letting InvokeAI split components.","Check folder contents for model_index.json/transformer before manual model installs."],"tags":["model-import","diffusers","invokeai","directory-structure"],"backgroundTag":"wrong-model-type-import","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}