invoke-ai/InvokeAI · error · ValueError

source_url must be a string

Error message

source_url must be a string

What it means

Pydantic field_validator for source_url on model config base raises ValueError when the supplied value is not a string (and not None/''). InvokeAI records where a model was downloaded from, and this guard keeps the field type-safe before schema validation.

Source

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

    source_type: ModelSourceType = Field(
        description="The type of source",
    )
    source_api_response: str | None = Field(
        default=None,
        description="The original API response from the source, as stringified JSON.",
    )
    source_url: str | None = Field(
        default=None,
        description="Optional URL for the model (e.g. download page or model page).",
    )

    @field_validator("source_url", mode="before")
    @classmethod
    def validate_source_url(cls, v: Any) -> str | None:
        if v is None or v == "":
            return None
        if not isinstance(v, str):
            raise ValueError("source_url must be a string")
        if not v.startswith(("https://", "http://")):
            raise ValueError("source_url must be an http or https URL")
        return v

    cover_image: str | None = Field(
        default=None,
        description="Url for image to preview model",
    )

    CONFIG_CLASSES: ClassVar[set[Type["Config_Base"]]] = set()
    """Set of all non-abstract subclasses of Config_Base, for use during model probing. In other words, this is the set
    of all known model config types."""

    model_config = ConfigDict(
        validate_assignment=True,
        json_schema_serialization_defaults_required=True,
        json_schema_mode_override="serialization",
    )

View on GitHub (pinned to 0b6a024f2f)

Solutions

  1. Coerce the value to str before assigning, or set it to None if unknown.
  2. If the value comes from YAML/JSON, quote or cast it (e.g. str(v)) so it parses as a string.
  3. Omit the field entirely if there is no source URL - None and '' are accepted and normalized to None.

Example fix

// before
config = {'source_url': 12345}
// after
config = {'source_url': 'https://huggingface.co/repo/model' if src else None}
Defensive patterns

Strategy: type-guard

Validate before calling

def sanitize_source_url(v):
    return None if v in (None, '') else (v if isinstance(v, str) else str(v))

Type guard

def is_str_or_none(v: object) -> TypeGuard[str | None]:
    return v is None or isinstance(v, str)

Try / catch

try:
    config = MainModelConfig(**cfg)
except ValueError as e:
    if 'source_url must be a string' in str(e):
        cfg['source_url'] = str(cfg['source_url'])
        config = MainModelConfig(**cfg)
    else:
        raise

Prevention

When it happens

Trigger: Creating/updating a ModelConfig (e.g. via model install APIs or YAML/DB import) with source_url set to a number, bytes, dict, or other non-string non-empty value.

Common situations: Programmatic config construction passing an int or object; deserializing records from another tool where source_url was stored as bytes; YAML with an unquoted value that parses as a non-string type.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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