PrefectHQ/fastmcp · error · ValueError
CIMD redirect_uris must be non-empty strings
Error message
CIMD redirect_uris must be non-empty strings
What it means
A Pydantic ValueError from the same redirect_uris validator (fastmcp_slim/fastmcp/server/auth/cimd.py:148) raised when an individual entry in redirect_uris is None, an empty string, or whitespace-only. Each advertised redirect URI must be a non-empty string to serve as a usable callback target.
Source
Thrown at fastmcp_slim/fastmcp/server/auth/cimd.py:155
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):
"""Raised when CIMD document fetching fails."""
View on GitHub (pinned to 1f02114297)
Solutions
- Remove empty/whitespace entries so redirect_uris contains only valid absolute URIs.
- If URIs come from environment variables, verify they are set and non-empty before generating the document.
- Filter and strip entries in the producing code: [u.strip() for u in uris if u and u.strip()].
Example fix
// before "redirect_uris": ["https://client.example.com/cb", ""] // after "redirect_uris": ["https://client.example.com/cb"]
Defensive patterns
Strategy: validation
Validate before calling
uris = doc.get('redirect_uris') or []
for uri in uris:
if not isinstance(uri, str) or not uri.strip():
raise ValueError(f'redirect_uris entries must be non-empty strings, got {uri!r}')
doc['redirect_uris'] = [u.strip() for u in uris if u and u.strip()] Type guard
def is_valid_redirect_entry(uri) -> bool:
return isinstance(uri, str) and bool(uri.strip()) Try / catch
from pydantic import ValidationError
try:
document = CIMDDocument.model_validate(raw_doc)
except ValidationError as e:
logger.error('Bad redirect_uri entry: %s', e)
raise HTTPException(400, 'invalid_client_metadata') from e Prevention
- Filter blank entries after building redirect_uris from comma-separated or env-var sources.
- Verify interpolated environment variables (e.g. CALLBACK_URL) are set before generating the document.
- Strip whitespace when serializing URI lists into JSON.
When it happens
Trigger: A CIMD document's redirect_uris array contains "" or " " (or a null coerced in), e.g. ["https://client.example.com/cb", ""] — the list is non-empty so the empty-list check doesn't fire, but this entry fails the `not uri or not uri.strip()` check.
Common situations: A trailing empty string left by splitting a comma-separated URI list; hand-edited JSON with a placeholder never replaced; environment-interpolated URI variables that expanded to empty (e.g. ${CALLBACK_URL} unset).
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
- CIMD documents must include at least one redirect_uri
- CIMD redirect_uri must have a scheme (e.g. http:// or https:
- CIMD documents cannot use shared-secret auth methods: {v}. U
- CIMD redirect_uri must have a host: {uri!r}
- The API key is empty
AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29).
Data as JSON: /api/errors/c3a69f162e46e589.
Report an issue: GitHub.