invoke-ai/InvokeAI · error · NotAMatchError
directory is not a full FLUX.2 pipeline (no model_index.json
Error message
directory is not a full FLUX.2 pipeline (no model_index.json and no transformer/ subfolder); a loose transformer-only checkout cannot be used as a FLUX.2 main model
What it means
from_model_on_disk for the FLUX.2 diffusers config rejects any directory that lacks both `model_index.json` and a `transformer/` subfolder. Without them the directory is not a complete FLUX.2 pipeline; the loader would append `vae/` and `text_encoder/` subpaths that don't exist and crash with an OSError mid-generation. Raising NotAMatchError makes the folder fall through to a non-main classification instead of registering as a broken pipeline.
Source
Thrown at invokeai/backend/model_manager/configs/main.py:1012
variant: Flux2VariantType = Field()
@classmethod
def from_model_on_disk(cls, mod: ModelOnDisk, override_fields: dict[str, Any]) -> Self:
raise_if_not_dir(mod)
raise_for_override_fields(cls, override_fields)
# A FLUX.2 *main* model is a full diffusers pipeline: a `model_index.json` at
# the root, or at least the transformer packaged as a `transformer/` subfolder.
# A loose transformer-only checkout — just the contents of `transformer/`, with
# a root `config.json` whose `_class_name` is `Flux2Transformer2DModel` — is NOT
# a usable main model: the loader unconditionally appends `vae/` / `text_encoder/`
# subfolders that don't exist and fails with an OSError mid-queue. Reject that
# layout here so it falls through to a non-main classification instead of
# registering as a broken pipeline. (The standalone `transformer/` still matches
# via the pipeline layout below when it ships inside a full folder.)
if not (mod.path / "model_index.json").exists() and not (mod.path / "transformer").exists():
raise NotAMatchError(
"directory is not a full FLUX.2 pipeline (no model_index.json and no transformer/ subfolder); "
"a loose transformer-only checkout cannot be used as a FLUX.2 main model"
)
# Check for FLUX.2-specific pipeline class names
raise_for_class_name(
common_config_paths(mod.path),
{
"Flux2KleinPipeline",
"Flux2Pipeline",
"Flux2Transformer2DModel",
},
)
# Reject SDNQ-quantized pipelines so the SDNQ-specific config matches them instead.
# Without this both configs accept the same folder and identification can latch onto
# the wrong one (the plain diffusers loader would then mis-read packed uint8 weights
# as bf16 and crash with size-mismatch errors at first inference).View on GitHub (pinned to 0b6a024f2f)
Solutions
- Use the full FLUX.2 pipeline repo/folder containing `model_index.json` plus `vae/`, `text_encoder/`, and `transformer/` subfolders.
- If you only have the transformer, either place it inside a complete pipeline folder (the standalone `transformer/` then matches via the pipeline layout) or use a checkpoint/single-file import path.
- Re-download if files were lost during transfer; verify `model_index.json` exists at the folder root before scanning.
Example fix
// before (loose checkout) models/flux.2/transformer/config.json // after (full pipeline) models/flux.2/model_index.json models/flux.2/transformer/config.json models/flux.2/vae/... models/flux.2/text_encoder/...
Defensive patterns
Strategy: validation
Validate before calling
from pathlib import Path
def validate_flux2_pipeline(folder: Path) -> None:
if not (folder / "model_index.json").exists() and not (folder / "transformer").exists():
raise ValueError(f"{folder} is not a full FLUX.2 pipeline: missing model_index.json and transformer/") Type guard
def is_full_flux2_pipeline(folder: Path) -> bool:
return (folder / "model_index.json").is_file() or (folder / "transformer").exists() Try / catch
try:
cfg = Main_Diffusers_Flux2_Config.from_model_on_disk(mod)
except NotAMatchError:
# not a complete pipeline; classify as non-main or guide user to re-download
cfg = None Prevention
- Always clone/download the entire FLUX.2 repo (model_index.json + vae/ + text_encoder/ + transformer/).
- Verify model_index.json exists at the folder root before adding the model to InvokeAI.
- Avoid pointing the models directory at a bare transformer-only checkout.
When it happens
Trigger: Scanning/installing a model folder where `model_index.json` is absent AND no `transformer/` entry exists, during FLUX.2 main-model identification via from_model_on_disk.
Common situations: Pointing InvokeAI at a bare diffusers `transformer/` checkout (e.g. only cloned the transformer subfolder of a FLUX.2 repo), a partial/interrupted download that dropped top-level files, or a folder holding only VAE or text-encoder components.
Related errors
- transformer is SDNQ-quantized; use Main_SDNQ_Diffusers_FLUX_
- unrecognized scheduler prediction_type {prediction_type}
- directory looks like a full diffusers pipeline (has model_in
- missing text_encoder_2/model.safetensors.index.json
- Missing LoRA layer: '{src_key}'.
AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29).
Data as JSON: /api/errors/097d3d13b135cd59.
Report an issue: GitHub.