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

  1. Use the full FLUX.2 pipeline repo/folder containing `model_index.json` plus `vae/`, `text_encoder/`, and `transformer/` subfolders.
  2. 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.
  3. 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

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


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