invoke-ai/InvokeAI · error · ValueError
The {model_name} model must be a FLUX.2 Klein pipeline, but
Error message
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.) What it means
_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.
Source
Thrown at invokeai/app/invocations/flux2_klein_model_loader.py:241
) -> None:
"""Validate a Diffusers pipeline used as the *text encoder* source.
The source's tokenizer + encoder are extracted and paired with *this* model's transformer,
so they must come from the same Qwen3 family. Mismatched widths produce conditioning that
only fails as an opaque matmul error deep in denoise, so reject it here where the user still
gets a clear message. The linear UI (``buildFLUXGraph``) and the standalone-encoder path
(``_validate_qwen3_encoder_variant``) already enforce the family match; the workflow editor
lets any FLUX.2 Diffusers pipeline be wired in here, so this is the entry point that closes it.
"""
config = self._validate_diffusers_format(context, model, model_name)
source_variant = getattr(config, "variant", None)
source_qwen3 = _KLEIN_TO_QWEN3_VARIANT.get(source_variant)
# An allowlist, not "reject [dev]": a future third FLUX.2 variant has to fail closed here
# the way the [dev] loader's guard already makes it, rather than being silently accepted.
if source_qwen3 is None:
described = f"variant '{source_variant.value}'" if source_variant is not None else "not a Klein pipeline"
raise ValueError(
f"The {model_name} model must be a FLUX.2 Klein pipeline, "
f"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.)"
)
required_qwen3 = _KLEIN_TO_QWEN3_VARIANT.get(getattr(main_config, "variant", None))
if required_qwen3 is not None and source_qwen3 != required_qwen3:
raise ValueError(
f"Qwen3 encoder variant mismatch: FLUX.2 Klein {main_config.variant.value} requires a "
f"{required_qwen3.value} encoder, but the {model_name} pipeline '{config.name}' "
f"({source_variant.value}) carries {source_qwen3.value}. "
"Select a Klein pipeline from the same family - 4B pairs with 4B, 9B with 9B."
)
def _validate_qwen3_encoder_variant(self, context: InvocationContext, main_config: AnyModelConfig) -> None:
"""Validate that the standalone Qwen3 encoder variant matches the FLUX.2 Klein variant.
View on GitHub (pinned to 0b6a024f2f)
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
Example fix
// before loader.qwen3_source_model = flux2_dev_pipeline # variant not Klein // after assert get_variant(context, flux2_klein_pipeline) in KLEIN_VARIANTS loader.qwen3_source_model = flux2_klein_pipeline
Defensive patterns
Strategy: validation
Validate before calling
cfg = context.models.get_config(source_model)
variant = getattr(cfg, 'variant', None)
if variant not in _KLEIN_TO_QWEN3_VARIANT:
raise ValueError(f"{cfg.name} is not a Klein pipeline (variant={variant})") Type guard
def is_klein_pipeline(config) -> bool:
return getattr(config, 'variant', None) in _KLEIN_TO_QWEN3_VARIANT Try / catch
try:
output = loader.invoke(context)
except ValueError as e:
if 'must be a FLUX.2 Klein pipeline' in str(e):
loader.qwen3_source_model = select_klein_pipeline(context)
output = loader.invoke(context)
else:
raise Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Qwen3 encoder variant mismatch: FLUX.2 Klein {main_config.va
- Qwen3 encoder variant mismatch: FLUX.2 Klein {main_config.va
- LoRA "{lora_key}" already applied to Qwen3 encoder.
- Expected PreTrainedModel for text encoder, got {type(text_en
- Expected PreTrainedTokenizerBase for tokenizer, got {type(to
AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29).
Data as JSON: /api/errors/efa4515f8c5c1bb1.
Report an issue: GitHub.