PrefectHQ/fastmcp · error · ValueError

CIMD documents must include at least one redirect_uri

Error message

CIMD documents must include at least one redirect_uri

What it means

A Pydantic ValueError raised by CIMDDocument's redirect_uris validator (fastmcp_slim/fastmcp/server/auth/cimd.py:148) when the document's redirect_uris list is empty. Per the CIMD draft, a client metadata document must advertise at least one redirect_uri for authorization-code flows, so an empty list makes the document invalid.

Source

Thrown at fastmcp_slim/fastmcp/server/auth/cimd.py:152

    @field_validator("token_endpoint_auth_method")
    @classmethod
    def validate_auth_method(cls, v: str) -> str:
        """Ensure no shared-secret auth methods are used."""
        forbidden = {"client_secret_post", "client_secret_basic", "client_secret_jwt"}
        if v in forbidden:
            raise ValueError(
                f"CIMD documents cannot use shared-secret auth methods: {v}. "
                "Use 'none' or 'private_key_jwt' instead."
            )
        return v

    @field_validator("redirect_uris")
    @classmethod
    def validate_redirect_uris(cls, v: list[str]) -> list[str]:
        """Ensure redirect_uris is non-empty and each entry is a valid URI."""
        if not v:
            raise ValueError("CIMD documents must include at least one redirect_uri")
        for uri in v:
            if not uri or not uri.strip():
                raise ValueError("CIMD redirect_uris must be non-empty strings")
            parsed = urlparse(uri)
            if not parsed.scheme:
                raise ValueError(
                    f"CIMD redirect_uri must have a scheme (e.g. http:// or https://): {uri!r}"
                )
            if not parsed.netloc and not uri.startswith("urn:"):
                raise ValueError(f"CIMD redirect_uri must have a host: {uri!r}")
        return v


class CIMDValidationError(Exception):
    """Raised when CIMD document validation fails."""


class CIMDFetchError(Exception):

View on GitHub (pinned to 1f02114297)

Solutions

  1. Add at least one absolute redirect_uri (e.g. 'https://client.example.com/callback') to the document's redirect_uris array.
  2. Curl the hosted CIMD document and inspect the JSON to confirm the URIs you expect are actually returned.
  3. Fix the document-generation code so redirect_uris is always populated before publishing.
  4. Confirm the correct client metadata URL is being fetched — a stale/empty document may be the one being read.

Example fix

// before
{"client_name": "My Client", "redirect_uris": []}
// after
{"client_name": "My Client", "redirect_uris": ["https://client.example.com/callback"]}
Defensive patterns

Strategy: validation

Validate before calling

doc = json.loads(raw_cimd_json)
uris = doc.get('redirect_uris') or []
if not uris:
    raise ValueError('CIMD document must declare at least one redirect_uri')

Type guard

def has_redirect_uris(doc: dict) -> bool:
    return bool(doc.get('redirect_uris'))

Try / catch

from pydantic import ValidationError
try:
    document = CIMDDocument.model_validate(raw_doc)
except ValidationError as e:
    logger.error('CIMD validation failed: %s', e)
    raise HTTPException(400, 'invalid_client_metadata') from e

Prevention

When it happens

Trigger: A fetched or hand-built CIMD JSON document has "redirect_uris": [] (or no entries), so the field validator receives an empty list and raises before the per-URI checks run.

Common situations: A client hosting a metadata document template with the redirect_uris array never filled in; programmatic document generation that appends redirect URIs only under a condition that never fired; a config export that redacted/stripped the URIs.

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 PrefectHQ/fastmcp@1f02114297 (2026-08-29). Data as JSON: /api/errors/7d6cd01834e46633. Report an issue: GitHub.