PrefectHQ/fastmcp · error · ValueError

CIMD redirect_uri must have a scheme (e.g. http:// or https:

Error message

CIMD redirect_uri must have a scheme (e.g. http:// or https://): {uri!r}

What it means

A Pydantic ValueError from the redirect_uris validator (fastmcp_slim/fastmcp/server/auth/cimd.py:148) raised when a redirect_uri entry is a non-empty string but urlparse finds no scheme. Redirect URIs must be absolute URLs (http:// or https://, or urn: URIs with a host); bare paths like '/callback' or schemeless hosts like 'client.example.com/cb' are rejected.

Source

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

        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):
    """Raised when CIMD document fetching fails."""


@dataclass
class _CIMDCacheEntry:
    """Cached CIMD document and associated HTTP cache metadata."""

View on GitHub (pinned to 1f02114297)

Solutions

  1. Use fully-qualified absolute URIs including the scheme, e.g. 'https://client.example.com/callback'.
  2. For native apps, register a proper custom-scheme or loopback URI (e.g. 'http://127.0.0.1:PORT/cb') rather than a bare path.
  3. Validate each URI with urllib.parse.urlparse locally before publishing: assert scheme and netloc are non-empty.
  4. Check for '://' typos in scheme syntax.

Example fix

// before
"redirect_uris": ["/oauth/callback"]
// after
"redirect_uris": ["https://client.example.com/oauth/callback"]
Defensive patterns

Strategy: validation

Validate before calling

from urllib.parse import urlparse
for uri in doc.get('redirect_uris', []):
    p = urlparse(uri)
    if not p.scheme or not (p.netloc or uri.startswith('urn:')):
        raise ValueError(f'redirect_uri must be absolute with scheme: {uri!r}')

Type guard

def is_absolute_uri(uri: str) -> bool:
    p = urlparse(uri)
    return bool(p.scheme) and (bool(p.netloc) or uri.startswith('urn:'))

Try / catch

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

Prevention

When it happens

Trigger: A CIMD document lists a relative path ('/oauth/callback'), a schemeless host ('client.example.com/cb'), or a mistyped scheme (e.g. 'https:/example.com/cb' with a single slash) in redirect_uris, so urlparse(uri).scheme comes back empty.

Common situations: Authoring the document with values copied from web-framework route paths instead of full URLs; assuming relative URIs will be resolved against the document URL (they will not); typos in the '://' scheme separator.

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/60b82e0c3b4f8a08. Report an issue: GitHub.