{"record":{"id":"c30eb9e4aee4a6b8","repo":"invoke-ai/InvokeAI","slug":"qwen3-encoder-variant-mismatch-flux-2-klein-main-c30eb9","errorCode":null,"errorMessage":"Qwen3 encoder variant mismatch: FLUX.2 Klein {main_config.variant.value} requires {expected_qwen3_variant.value} encoder, but {qwen3_variant.value} was selected. Please select a matching Qwen3 encoder or use a Diffusers format model which includes the correct encoder.","messagePattern":"Qwen3 encoder variant mismatch: FLUX\\.2 Klein (.+?) requires (.+?) encoder, but (.+?) was selected\\. Please select a matching Qwen3 encoder or use a Diffusers format model which includes the correct encoder\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"invokeai/app/invocations/flux2_klein_model_loader.py","lineNumber":275,"sourceCode":"    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\n        - FLUX.2 Klein 4B (and 4B Base) require the Qwen3 4B encoder\n        - FLUX.2 Klein 9B (and 9B Base) require the Qwen3 8B encoder\n        \"\"\"\n        if self.qwen3_encoder_model is None:\n            return\n\n        # `getattr(..., None)` rather than `hasattr`: the field can exist and still be None, and\n        # comparing None against the expected variant would then raise `AttributeError` on\n        # `.value` in the error path instead of the intended `ValueError`.\n        qwen3_variant = getattr(context.models.get_config(self.qwen3_encoder_model), \"variant\", None)\n        if qwen3_variant is None:\n            return\n\n        expected_qwen3_variant = _KLEIN_TO_QWEN3_VARIANT.get(getattr(main_config, \"variant\", None))\n        if expected_qwen3_variant is not None and qwen3_variant != expected_qwen3_variant:\n            raise ValueError(\n                f\"Qwen3 encoder variant mismatch: FLUX.2 Klein {main_config.variant.value} requires \"\n                f\"{expected_qwen3_variant.value} encoder, but {qwen3_variant.value} was selected. \"\n                \"Please select a matching Qwen3 encoder or use a Diffusers format model which includes the correct encoder.\"\n            )\n","sourceCodeStart":257,"sourceCodeEnd":280,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/app/invocations/flux2_klein_model_loader.py#L257-L280","documentation":"_validate_qwen3_encoder_variant raised ValueError because the standalone Qwen3 encoder selected via 'Qwen3 Encoder' has a variant that differs from the one required by the main Klein model's variant (e.g. Qwen3 8B chosen for Klein 4B). The check is skipped when the encoder config has no variant. The message suggests a matching encoder or a Diffusers model bundling the right one.","triggerScenarios":"invoke() -> _validate_qwen3_encoder_variant where qwen3_variant = context.models.get_config(self.qwen3_encoder_model).variant is not None, expected_qwen3_variant = _KLEIN_TO_QWEN3_VARIANT[main_config.variant] exists, and the two differ.","commonSituations":"Klein 4B workflow wired to a Qwen3 8B encoder (or 9B to 4B); user selected the only Qwen3 encoder installed regardless of size; variant metadata wrong after manual model import.","solutions":["Select the Qwen3 encoder matching the main model's family (Qwen3 4B for Klein 4B, Qwen3 8B for Klein 9B)","Switch to a Diffusers-format Klein model whose bundled encoder is guaranteed correct","Install the missing matching Qwen3 encoder via the model manager","Fix variant metadata if the encoder is actually the right size but tagged incorrectly","Catch ValueError and compare variants before invoke()"],"exampleFix":"// before\nloader.qwen3_encoder_model = qwen3_8b_encoder  # main model is Klein 4B\n// after\nmain_cfg = context.models.get_config(loader.model)\nenc_cfg = context.models.get_config(loader.qwen3_encoder_model)\nassert _KLEIN_TO_QWEN3_VARIANT[main_cfg.variant] == enc_cfg.variant\noutput = loader.invoke(context)","handlingStrategy":"validation","validationCode":"main_cfg = context.models.get_config(loader.model)\nenc_cfg = context.models.get_config(loader.qwen3_encoder_model)\nexpected = _KLEIN_TO_QWEN3_VARIANT.get(getattr(main_cfg, 'variant', None))\nenc_variant = getattr(enc_cfg, 'variant', None)\nif expected is not None and enc_variant is not None and enc_variant != expected:\n    raise ValueError(f\"need {expected} encoder, got {enc_variant}\")","typeGuard":"def encoder_variant_ok(main_cfg, encoder_cfg) -> bool:\n    expected = _KLEIN_TO_QWEN3_VARIANT.get(getattr(main_cfg, 'variant', None))\n    enc = getattr(encoder_cfg, 'variant', None)\n    return expected is None or enc is None or enc == expected","tryCatchPattern":"try:\n    output = loader.invoke(context)\nexcept ValueError as e:\n    if 'Qwen3 encoder variant mismatch' in str(e) and 'was selected' in str(e):\n        loader.qwen3_encoder_model = select_matching_qwen3_encoder(loader.model, context)\n        output = loader.invoke(context)\n    else:\n        raise","preventionTips":["Install both Qwen3 4B and 8B encoders so a matching one is always available","Verify encoder variant against main model variant before invoking","Use Diffusers Klein models when unsure, since the bundled encoder always matches"],"tags":["variant-mismatch","qwen3","text-encoder","invokeai"],"backgroundTag":"encoder-variant-mismatch","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}