{"record":{"id":"7d6cd01834e46633","repo":"PrefectHQ/fastmcp","slug":"cimd-documents-must-include-at-least-one-redirect","errorCode":null,"errorMessage":"CIMD documents must include at least one redirect_uri","messagePattern":"CIMD documents must include at least one redirect_uri","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"fastmcp_slim/fastmcp/server/auth/cimd.py","lineNumber":152,"sourceCode":"\n    @field_validator(\"token_endpoint_auth_method\")\n    @classmethod\n    def validate_auth_method(cls, v: str) -> str:\n        \"\"\"Ensure no shared-secret auth methods are used.\"\"\"\n        forbidden = {\"client_secret_post\", \"client_secret_basic\", \"client_secret_jwt\"}\n        if v in forbidden:\n            raise ValueError(\n                f\"CIMD documents cannot use shared-secret auth methods: {v}. \"\n                \"Use 'none' or 'private_key_jwt' instead.\"\n            )\n        return v\n\n    @field_validator(\"redirect_uris\")\n    @classmethod\n    def validate_redirect_uris(cls, v: list[str]) -> list[str]:\n        \"\"\"Ensure redirect_uris is non-empty and each entry is a valid URI.\"\"\"\n        if not v:\n            raise ValueError(\"CIMD documents must include at least one redirect_uri\")\n        for uri in v:\n            if not uri or not uri.strip():\n                raise ValueError(\"CIMD redirect_uris must be non-empty strings\")\n            parsed = urlparse(uri)\n            if not parsed.scheme:\n                raise ValueError(\n                    f\"CIMD redirect_uri must have a scheme (e.g. http:// or https://): {uri!r}\"\n                )\n            if not parsed.netloc and not uri.startswith(\"urn:\"):\n                raise ValueError(f\"CIMD redirect_uri must have a host: {uri!r}\")\n        return v\n\n\nclass CIMDValidationError(Exception):\n    \"\"\"Raised when CIMD document validation fails.\"\"\"\n\n\nclass CIMDFetchError(Exception):","sourceCodeStart":134,"sourceCodeEnd":170,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/server/auth/cimd.py#L134-L170","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Add at least one absolute redirect_uri (e.g. 'https://client.example.com/callback') to the document's redirect_uris array.","Curl the hosted CIMD document and inspect the JSON to confirm the URIs you expect are actually returned.","Fix the document-generation code so redirect_uris is always populated before publishing.","Confirm the correct client metadata URL is being fetched — a stale/empty document may be the one being read."],"exampleFix":"// before\n{\"client_name\": \"My Client\", \"redirect_uris\": []}\n// after\n{\"client_name\": \"My Client\", \"redirect_uris\": [\"https://client.example.com/callback\"]}","handlingStrategy":"validation","validationCode":"doc = json.loads(raw_cimd_json)\nuris = doc.get('redirect_uris') or []\nif not uris:\n    raise ValueError('CIMD document must declare at least one redirect_uri')","typeGuard":"def has_redirect_uris(doc: dict) -> bool:\n    return bool(doc.get('redirect_uris'))","tryCatchPattern":"from pydantic import ValidationError\ntry:\n    document = CIMDDocument.model_validate(raw_doc)\nexcept ValidationError as e:\n    logger.error('CIMD validation failed: %s', e)\n    raise HTTPException(400, 'invalid_client_metadata') from e","preventionTips":["Always populate redirect_uris with at least one absolute callback URL before publishing.","Fetch your CIMD URL in CI and assert the expected URIs are present.","Fail fast in document generators if no callback URL is configured."],"tags":["pydantic","cimd","validation","redirect-uri"],"backgroundTag":"schema-validation-failed","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}