{"record":{"id":"873f75be62c3a03b","repo":"invoke-ai/InvokeAI","slug":"directory-looks-like-a-full-diffusers-pipeline-ha","errorCode":null,"errorMessage":"directory looks like a full diffusers pipeline (has model_index.json or transformer folder), not a standalone Qwen3 encoder","messagePattern":"directory looks like a full diffusers pipeline \\(has model_index\\.json or transformer folder\\), not a standalone Qwen3 encoder","errorType":"exception","errorClass":"NotAMatchError","httpStatus":null,"severity":"info","filePath":"invokeai/backend/model_manager/configs/qwen3_encoder.py","lineNumber":300,"sourceCode":"\n    base: Literal[BaseModelType.Any] = Field(default=BaseModelType.Any)\n    type: Literal[ModelType.Qwen3Encoder] = Field(default=ModelType.Qwen3Encoder)\n    format: Literal[ModelFormat.Qwen3Encoder] = Field(default=ModelFormat.Qwen3Encoder)\n    cpu_only: bool | None = Field(default=None, description=\"Whether this model should run on CPU only\")\n    variant: Qwen3VariantType = Field(description=\"Qwen3 model size variant (4B or 8B)\")\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 Qwen3 encoders.\n        # Full pipelines have model_index.json at root (diffusers format) or a transformer subfolder.\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 encoder\"\n            )\n\n        # Check for text_encoder config - support both:\n        # 1. Full model structure: model_root/text_encoder/config.json\n        # 2. Standalone text_encoder download: model_root/config.json (when text_encoder subfolder is downloaded separately)\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            # Standalone text_encoder downloads do not bundle tokenizer files. If we see tokenizer files at the\n            # root next to config.json, this is a complete causal LM (TextLLM), not a Qwen3 encoder subfolder.\n            tokenizer_files = (\"tokenizer.json\", \"tokenizer.model\", \"tokenizer_config.json\")\n            if any((mod.path / f).exists() for f in tokenizer_files):\n                raise NotAMatchError(","sourceCodeStart":282,"sourceCodeEnd":318,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/backend/model_manager/configs/qwen3_encoder.py#L282-L318","documentation":"NotAMatchError raised in Qwen3Encoder_Qwen3Encoder_Config.from_model_on_disk (qwen3_encoder.py:300). The scanned directory is a full diffusers pipeline (it has model_index.json at root or a transformer/ subfolder), so it must be registered as a main pipeline model, not as a standalone Qwen3 text encoder. The guard prevents the Qwen3Encoder config from claiming whole pipelines.","triggerScenarios":"Running model scan/install on a directory containing model_index.json or a transformer/ subfolder while the Qwen3Encoder config's from_model_on_disk probes it.","commonSituations":"Pointing InvokeAI at a full HuggingFace pipeline checkout (e.g. a FLUX.2 or Z-Image repo root) and expecting only the encoder to be imported; downloading a whole repo with git clone instead of only the text_encoder subfolder.","solutions":["Install the directory as a main pipeline model — InvokeAI should match it with the appropriate pipeline config.","If you only need the encoder, download just the text_encoder/ subfolder into its own directory and scan that.","Move the full pipeline out of the folder being scanned as an encoder candidate.","If you believe this is a false positive, rename/remove a stray model_index.json or transformer/ dir that leaked into the encoder folder."],"exampleFix":"// before\nmodels/z-image/  // full pipeline: model_index.json + transformer/ + text_encoder/\n// after\nmodels/z-image/ installed as pipeline; models/z-image-text-encoder/ containing only text_encoder/ contents","handlingStrategy":"validation","validationCode":"def is_full_pipeline(path) -> bool:\n    return (path / 'model_index.json').exists() or (path / 'transformer').is_dir()  # install as main pipeline model","typeGuard":"def is_standalone_encoder_dir(path) -> bool:\n    return not (path / 'model_index.json').exists() and not (path / 'transformer').exists() and ((path / 'text_encoder' / 'config.json').exists() or (path / 'config.json').exists())","tryCatchPattern":"if is_full_pipeline(model_dir):\n    install_as_pipeline(model_dir)\nelse:\n    try:\n        install_as_encoder(model_dir)\n    except NotAMatchError as e:\n        logger.warning('Encoder install failed: %s', e)","preventionTips":["Download only the text_encoder/ subfolder when you need a standalone encoder.","Install full pipeline repos (model_index.json present) as main models.","Never clone entire pipeline repos into encoder scan directories."],"tags":["diffusers","model-identification","directory-structure","qwen3"],"backgroundTag":"model-not-a-match","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}