invoke-ai/InvokeAI · error · ValueError

Model config dict 'type' field must be a string or Enum

Error message

Model config dict 'type' field must be a string or Enum

What it means

get_model_discriminator_value builds a pydantic discriminated-union tag from a config dict's 'type' field, which must be a string or an Enum. Any other type raises ValueError so pydantic can route to the correct model config class.

Source

Thrown at invokeai/backend/model_manager/configs/base.py:170

    @staticmethod
    def get_model_discriminator_value(v: Any) -> str:
        """Computes the discriminator value for a model config discriminated union."""
        # This is called by pydantic during deserialization and serialization to determine which model the data
        # represents. It can get either a dict (during deserialization) or an instance of a Config_Base subclass
        # (during serialization).
        #
        # See: https://docs.pydantic.dev/latest/concepts/unions/#discriminated-unions-with-callable-discriminator
        if isinstance(v, Config_Base):
            # We have an instance of a ModelConfigBase subclass - use its tag directly.
            return v.get_tag().tag
        if isinstance(v, dict):
            # We have a dict - attempt to compute a tag from its fields.
            tag_strings: list[str] = []
            if type_ := v.get("type"):
                if isinstance(type_, Enum):
                    type_ = str(type_.value)
                elif not isinstance(type_, str):
                    raise ValueError("Model config dict 'type' field must be a string or Enum")
                tag_strings.append(type_)

            if format_ := v.get("format"):
                if isinstance(format_, Enum):
                    format_ = str(format_.value)
                elif not isinstance(format_, str):
                    raise ValueError("Model config dict 'format' field must be a string or Enum")
                tag_strings.append(format_)

            if base_ := v.get("base"):
                if isinstance(base_, Enum):
                    base_ = str(base_.value)
                elif not isinstance(base_, str):
                    raise ValueError("Model config dict 'base' field must be a string or Enum")
                tag_strings.append(base_)

            # Special case: CLIP Embed models also need the variant to distinguish them.
            if (

View on GitHub (pinned to 0b6a024f2f)

Solutions

  1. Pass the enum value string: {'type': ModelType.Main.value} or simply {'type': 'main'}.
  2. Pass the Enum member itself (isinstance Enum is accepted and converted).
  3. Fix serialization upstream so enums are dumped with use_enum_values or as strings, not ints/bytes.

Example fix

// before
{'type': 3, 'format': 'diffusers', 'base': 'sd-1'}
// after
{'type': ModelType.Main.value, 'format': 'diffusers', 'base': BaseModelType.StableDiffusion1.value}
Defensive patterns

Strategy: validation

Validate before calling

from enum import Enum

def valid_discriminator_field(v) -> bool:
    return isinstance(v, (str, Enum))

Type guard

def is_str_or_enum(v: object) -> TypeGuard[str | Enum]:
    return isinstance(v, (str, Enum))

Try / catch

try:
    config = AnyModelConfig(**cfg)
except ValueError as e:
    if "'type' field must be a string or Enum" in str(e):
        cfg['type'] = cfg['type'].value if isinstance(cfg['type'], Enum) else str(cfg['type'])
        config = AnyModelConfig(**cfg)
    else:
        raise

Prevention

When it happens

Trigger: Instantiating a model config (ModelConfigBase or subclass) from a dict whose 'type' is an int, ModelType-typed wrapper, bytes, or other non-str/non-Enum value.

Common situations: Loading configs from JSON where enums were serialized as integers; hand-writing a config dict with the wrong type; passing a ModelType instance that is not an Enum (e.g. a plain dataclass).

Related errors


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