{"record":{"id":"efa4515f8c5c1bb1","repo":"invoke-ai/InvokeAI","slug":"the-model-name-model-must-be-a-flux-2-klein-pipe","errorCode":null,"errorMessage":"The {model_name} model must be a FLUX.2 Klein pipeline, but the selected model '{config.name}' is {described}. Its text encoder is incompatible with the Klein transformer. (Its VAE is compatible - this only blocks encoder extraction.)","messagePattern":"The (.+?) model must be a FLUX\\.2 Klein pipeline, but the selected model '(.+?)' is (.+?)\\. Its text encoder is incompatible with the Klein transformer\\. \\(Its VAE is compatible - this only blocks encoder extraction\\.\\)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"invokeai/app/invocations/flux2_klein_model_loader.py","lineNumber":241,"sourceCode":"    ) -> None:\n        \"\"\"Validate a Diffusers pipeline used as the *text encoder* source.\n\n        The source's tokenizer + encoder are extracted and paired with *this* model's transformer,\n        so they must come from the same Qwen3 family. Mismatched widths produce conditioning that\n        only fails as an opaque matmul error deep in denoise, so reject it here where the user still\n        gets a clear message. The linear UI (``buildFLUXGraph``) and the standalone-encoder path\n        (``_validate_qwen3_encoder_variant``) already enforce the family match; the workflow editor\n        lets any FLUX.2 Diffusers pipeline be wired in here, so this is the entry point that closes it.\n        \"\"\"\n        config = self._validate_diffusers_format(context, model, model_name)\n        source_variant = getattr(config, \"variant\", None)\n        source_qwen3 = _KLEIN_TO_QWEN3_VARIANT.get(source_variant)\n\n        # An allowlist, not \"reject [dev]\": a future third FLUX.2 variant has to fail closed here\n        # the way the [dev] loader's guard already makes it, rather than being silently accepted.\n        if source_qwen3 is None:\n            described = f\"variant '{source_variant.value}'\" if source_variant is not None else \"not a Klein pipeline\"\n            raise ValueError(\n                f\"The {model_name} model must be a FLUX.2 Klein pipeline, \"\n                f\"but the selected model '{config.name}' is {described}. \"\n                \"Its text encoder is incompatible with the Klein transformer. \"\n                \"(Its VAE is compatible - this only blocks encoder extraction.)\"\n            )\n\n        required_qwen3 = _KLEIN_TO_QWEN3_VARIANT.get(getattr(main_config, \"variant\", None))\n        if required_qwen3 is not None and source_qwen3 != required_qwen3:\n            raise ValueError(\n                f\"Qwen3 encoder variant mismatch: FLUX.2 Klein {main_config.variant.value} requires a \"\n                f\"{required_qwen3.value} encoder, but the {model_name} pipeline '{config.name}' \"\n                f\"({source_variant.value}) carries {source_qwen3.value}. \"\n                \"Select a Klein pipeline from the same family - 4B pairs with 4B, 9B with 9B.\"\n            )\n\n    def _validate_qwen3_encoder_variant(self, context: InvocationContext, main_config: AnyModelConfig) -> None:\n        \"\"\"Validate that the standalone Qwen3 encoder variant matches the FLUX.2 Klein variant.\n","sourceCodeStart":223,"sourceCodeEnd":259,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/app/invocations/flux2_klein_model_loader.py#L223-L259","documentation":"_validate_encoder_source raised ValueError because the source pipeline's variant is not one of the FLUX.2 Klein variants mapped in _KLEIN_TO_QWEN3_VARIANT (fails closed for unknown/future variants and for non-Klein pipelines). The text encoder of such a pipeline is incompatible with the Klein transformer; its VAE would be fine, but encoder extraction is blocked.","triggerScenarios":"invoke() calls _validate_encoder_source with a model whose main config variant is None (not a Klein pipeline) or a variant with no entry in _KLEIN_TO_QWEN3_VARIANT (e.g. FLUX.2 dev/pro or an unrecognized variant), so source_qwen3 is None.","commonSituations":"Using a FLUX.2 dev pipeline as the 'Qwen3 Source' for a Klein model; a model record with a missing/unknown variant field; a newly released third FLUX.2 variant not yet in the allowlist.","solutions":["Choose a FLUX.2 Klein Diffusers pipeline (4B or 9B) as the encoder source","Fix the model's variant metadata in the model manager if it is actually a Klein pipeline but recorded wrong","Extract the text encoder separately and supply it via 'Qwen3 Encoder' instead of pipeline extraction","Catch ValueError and check the variant against _KLEIN_TO_QWEN3_VARIANT before wiring the source"],"exampleFix":"// before\nloader.qwen3_source_model = flux2_dev_pipeline   # variant not Klein\n// after\nassert get_variant(context, flux2_klein_pipeline) in KLEIN_VARIANTS\nloader.qwen3_source_model = flux2_klein_pipeline","handlingStrategy":"validation","validationCode":"cfg = context.models.get_config(source_model)\nvariant = getattr(cfg, 'variant', None)\nif variant not in _KLEIN_TO_QWEN3_VARIANT:\n    raise ValueError(f\"{cfg.name} is not a Klein pipeline (variant={variant})\")","typeGuard":"def is_klein_pipeline(config) -> bool:\n    return getattr(config, 'variant', None) in _KLEIN_TO_QWEN3_VARIANT","tryCatchPattern":"try:\n    output = loader.invoke(context)\nexcept ValueError as e:\n    if 'must be a FLUX.2 Klein pipeline' in str(e):\n        loader.qwen3_source_model = select_klein_pipeline(context)\n        output = loader.invoke(context)\n    else:\n        raise","preventionTips":["Keep FLUX.2 dev/pro pipelines out of Klein encoder-source slots","Check the model's variant field before wiring it as encoder source","Update the allowlist when new FLUX.2 variants are supported"],"tags":["variant-mismatch","qwen3","flux2-klein","invokeai"],"backgroundTag":"encoder-variant-incompatible","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}