invoke-ai/InvokeAI · error · RuntimeError

Mistral encoder returned only {num_layers} hidden layer(s),

Error message

Mistral encoder returned only {num_layers} hidden layer(s), but FLUX.2 [dev] reads layers {DEV_EXTRACTION_LAYERS} and requires at least {max(DEV_EXTRACTION_LAYERS)}. This is not a supported FLUX.2 [dev] text encoder.

What it means

_encode_prompt throws this RuntimeError when the Mistral encoder has fewer hidden layers than FLUX.2 [dev] requires. FLUX.2 [dev]'s joint attention was trained to read hidden states from layers DEV_EXTRACTION_LAYERS (10/20/30), so an encoder with fewer than 30 layers cannot satisfy the extraction indices. Rather than inventing indices that would yield degraded embeddings, the encoder is rejected loudly.

Source

Thrown at invokeai/app/invocations/flux2_dev_text_encoder.py:228

            use_cache=False,
        )
        if not hasattr(outputs, "hidden_states") or outputs.hidden_states is None:
            raise RuntimeError(
                "Mistral encoder did not return hidden_states. "
                "Ensure output_hidden_states=True is supported by this model."
            )
        num_hidden_states = len(outputs.hidden_states)  # = num_hidden_layers + 1 (embedding output)
        num_layers = num_hidden_states - 1

        # The standalone Mistral encoder loaders only accept 30-layer cow or 40-layer
        # Mistral Small 3 weights, so hidden_states[] should always contain the layers
        # FLUX.2 [dev]'s joint attention was trained to read (10/20/30). A text encoder
        # extracted from a Main_Diffusers_Flux2 pipeline, however, is loaded via generic
        # from_pretrained with no layer-count validation — so a nonstandard pipeline with
        # a <30-layer encoder could reach here. Fail loudly instead of inventing extraction
        # indices that would silently produce off-distribution (degraded) embeddings.
        if num_layers < max(DEV_EXTRACTION_LAYERS):
            raise RuntimeError(
                f"Mistral encoder returned only {num_layers} hidden layer(s), but FLUX.2 [dev] reads "
                f"layers {DEV_EXTRACTION_LAYERS} and requires at least {max(DEV_EXTRACTION_LAYERS)}. "
                "This is not a supported FLUX.2 [dev] text encoder."
            )
        extraction_layers = DEV_EXTRACTION_LAYERS

        # Concatenate the selected layers along the hidden dim: (B, seq, 3 * hidden_size).
        # This is byte-identical to stack(dim=1).permute(0,2,1,3).reshape(...) but avoids
        # the two intermediate full copies that stack + permute-reshape would allocate.
        prompt_embeds = torch.cat([outputs.hidden_states[i] for i in extraction_layers], dim=-1)
        prompt_embeds = prompt_embeds.to(dtype=text_encoder.dtype, device=device)

        return prompt_embeds

    def _lora_iterator(self, context: InvocationContext) -> Iterator[Tuple[ModelPatchRaw, float]]:
        """Iterate over LoRAs to apply to the Mistral encoder."""
        for lora in self.mistral_encoder.loras:
            lora_info = context.models.load(lora.lora)

View on GitHub (pinned to 0b6a024f2f)

Solutions

  1. Supply the full Mistral Small 3.1 text encoder (with at least 30 hidden layers) as the encoder source.
  2. Extract the encoder from a genuine FLUX.2 [dev] Diffusers pipeline rather than a nonstandard or distilled pipeline.
  3. Verify the encoder config's num_hidden_layers is >= 30 before loading.

Example fix

// before
encoder = tiny_distilled_mistral_encoder  // 16 layers
// after
encoder = mistral_small_3_1_full  // >= 30 layers
Defensive patterns

Strategy: validation

Validate before calling

cfg = encoder.config
if getattr(cfg, "num_hidden_layers", 0) < max(DEV_EXTRACTION_LAYERS):
    raise ValueError(f"Encoder has {cfg.num_hidden_layers} layers; FLUX.2 [dev] needs >= {max(DEV_EXTRACTION_LAYERS)}")

Type guard

def supports_flux2_dev_extraction(encoder) -> bool:
    return getattr(encoder.config, "num_hidden_layers", 0) >= max(DEV_EXTRACTION_LAYERS)

Try / catch

try:
    output = text_encoder_invocation.invoke(context)
except RuntimeError as e:
    if "hidden layer(s)" in str(e) and "not a supported FLUX.2 [dev] text encoder" in str(e):
        encoder = load_full_mistral_small_3_1()
        output = retry_encoding(encoder)
    else:
        raise

Prevention

When it happens

Trigger: outputs.hidden_states has length <= 30 (num_layers < max(DEV_EXTRACTION_LAYERS)); possible because Diffusers-pipeline encoders load via generic from_pretrained with no layer validation.

Common situations: A nonstandard FLUX.2 Diffusers pipeline with a small/short Mistral-compatible encoder (e.g. a distilled or Klein-family encoder) is supplied as the encoder source and passes earlier checks.

Related errors


AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29). Data as JSON: /api/errors/094fb45b4f0a0c2c. Report an issue: GitHub.