{"record":{"id":"6edecdfeaaeeccdb","repo":"PrefectHQ/fastmcp","slug":"cimd-redirect-uri-must-have-a-host-uri-r","errorCode":null,"errorMessage":"CIMD redirect_uri must have a host: {uri!r}","messagePattern":"CIMD redirect_uri must have a host: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"fastmcp_slim/fastmcp/server/auth/cimd.py","lineNumber":162,"sourceCode":"            )\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):\n    \"\"\"Raised when CIMD document fetching fails.\"\"\"\n\n\n@dataclass\nclass _CIMDCacheEntry:\n    \"\"\"Cached CIMD document and associated HTTP cache metadata.\"\"\"\n\n    doc: CIMDDocument\n    etag: str | None\n    last_modified: str | None","sourceCodeStart":144,"sourceCodeEnd":180,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/server/auth/cimd.py#L144-L180","documentation":"The CIMD document's redirect_uris validator requires every redirect URI to parse into a scheme and a network location (host). A URI with a scheme but no host (e.g. 'https:///callback' or 'myapp://') is rejected because the OAuth server cannot meaningfully match or redirect to it. Only 'urn:' URIs are exempted from the host requirement per RFC 8252 conventions.","triggerScenarios":"CIMDDocument.model_validate() on a document whose redirect_uris contains an entry like 'https:///callback', 'mailto:foo', or any scheme-qualified URI missing a host component; the validator runs inside CIMDFetcher.fetch() and CIMDClientManager flows that validate CIMD documents.","commonSituations":"Hand-authored CIMD JSON documents hosted by the client developer; custom-scheme mobile redirect URIs written without an authority (e.g. 'com.example.app:/oauth' instead of 'com.example.app://redirect'); copy-paste errors dropping the host portion of a URL.","solutions":["Fix the redirect_uri in the hosted CIMD document to include a host, e.g. 'https://app.example.com/callback'","For native apps using custom schemes, use a scheme+host form like 'com.example.app://oauth/callback' (or an exempted 'urn:ietf:wg:oauth:2.0:oob' style URI)","Re-host the corrected document and ensure the client_id URL still matches, then retry"],"exampleFix":"// before (CIMD document JSON)\n\"redirect_uris\": [\"https:///callback\"]\n// after\n\"redirect_uris\": [\"https://app.example.com/callback\"]","handlingStrategy":"validation","validationCode":"from urllib.parse import urlparse\ndef valid_redirect_uri(uri: str) -> bool:\n    p = urlparse(uri)\n    return bool(p.scheme) and (bool(p.netloc) or uri.startswith(\"urn:\"))\nuris = doc.get(\"redirect_uris\", [])\nassert uris and all(valid_redirect_uri(u) for u in uris), \"bad redirect_uris\"","typeGuard":"def is_absolute_uri(u: object) -> bool:\n    return isinstance(u, str) and bool(urlparse(u).netloc)","tryCatchPattern":"try:\n    doc = CIMDDocument.model_validate(data)\nexcept ValidationError as e:\n    ...  # surface per-field messages for redirect_uris","preventionTips":["Always publish redirect_uris as absolute URIs with scheme and host","Use scheme://host form for custom app schemes, not scheme:path","Validate your CIMD document locally with CIMDDocument.model_validate before hosting it"],"tags":["oauth","cimd","validation","redirect-uri"],"backgroundTag":"invalid-redirect-uri","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}