invoke-ai/InvokeAI · error · NotAMatchError

missing config.json at {config_path}

Error message

missing config.json at {config_path}

What it means

The Gemma2 encoder config expects a standalone encoder directory containing config.json at its root. If that file is missing, from_model_on_disk raises NotAMatchError, indicating this directory is not a Gemma2 text encoder as far as the prober can tell.

Source

Thrown at invokeai/backend/model_manager/configs/gemma2_encoder.py:63

            config.json             # architectures: ["Gemma2ForCausalLM"]
            tokenizer.json
            tokenizer_config.json
            model-*.safetensors     # or model.safetensors / *.bin
    """

    base: Literal[BaseModelType.Any] = Field(default=BaseModelType.Any)
    type: Literal[ModelType.Gemma2Encoder] = Field(default=ModelType.Gemma2Encoder)
    format: Literal[ModelFormat.Gemma2Encoder] = Field(default=ModelFormat.Gemma2Encoder)
    cpu_only: bool | None = Field(default=None, description="Whether this model should run on CPU only")

    @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)

        config_path = mod.path / "config.json"
        if not config_path.exists():
            raise NotAMatchError(f"missing config.json at {config_path}")

        # Reject full diffusers pipelines (they have model_index.json at root).
        if (mod.path / "model_index.json").exists():
            raise NotAMatchError("directory looks like a full diffusers pipeline, not a standalone Gemma2 encoder")

        # Architecture marker is the canonical signal.
        raise_for_class_name(config_path, {"Gemma2ForCausalLM"})

        # Only Gemma-2-2b (2304-dim hidden state) is compatible with PiD's fixed caption projection.
        # Reject 9B/27B variants here so they are not offered as compatible encoders and then fail with
        # a matrix-shape error deep inside PiD inference.
        hidden_size = get_config_dict_or_raise(config_path).get("hidden_size")
        if hidden_size != _PID_GEMMA_HIDDEN_SIZE:
            raise NotAMatchError(
                f"Gemma2 hidden_size {hidden_size} is incompatible with PiD, which requires "
                f"{_PID_GEMMA_HIDDEN_SIZE} (Gemma-2-2b); 9B/27B variants are not supported."
            )

View on GitHub (pinned to 0b6a024f2f)

Solutions

  1. Point at the directory directly containing config.json (the encoder folder itself)
  2. Re-download the encoder from HuggingFace so config.json is included
  3. Copy the matching config.json from the official Gemma2 repo into the directory
  4. Do not probe a parent/aggregator directory; probe each component directory individually

Example fix

// before
install_model("/models/pid")               # parent dir, no config.json at root
// after
install_model("/models/pid/text_encoder")  # contains config.json
Defensive patterns

Strategy: validation

Validate before calling

import pathlib

def is_standalone_encoder_dir(path: str) -> bool:
    p = pathlib.Path(path)
    return p.is_dir() and (p / "config.json").exists()

Try / catch

try:
    config = probe(mod)
except NotAMatchError as e:
    if "missing config.json" in str(e):
        logger.error("Point at the encoder directory containing config.json")
    else:
        raise

Prevention

When it happens

Trigger: Probing a directory that lacks config.json — a directory of raw weights only, a parent directory one level above the encoder folder, or a model stored in a non-diffusers layout.

Common situations: Pointing at the wrong nesting level of a downloaded repo; an incomplete HF download that skipped config.json; a manually assembled folder with only safetensors weights.

Related errors


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