{"record":{"id":"cc9d57cfad81ddc4","repo":"PrefectHQ/fastmcp","slug":"invalid-cimd-document-e","errorCode":null,"errorMessage":"Invalid CIMD document: {e}","messagePattern":"Invalid CIMD document: (.+?)","errorType":"validation","errorClass":"CIMDValidationError","httpStatus":null,"severity":"error","filePath":"fastmcp_slim/fastmcp/server/auth/cimd.py","lineNumber":415,"sourceCode":"                        must_revalidate=policy.must_revalidate,\n                    ),\n                )\n            else:\n                self._remove_cache_entry(client_id_url)\n            return cached.doc\n\n        now = time.time()\n        policy = self._parse_cache_policy(response.headers, now)\n\n        try:\n            data = json.loads(response.content)\n        except json.JSONDecodeError as e:\n            raise CIMDValidationError(f\"CIMD document is not valid JSON: {e}\") from e\n\n        try:\n            doc = CIMDDocument.model_validate(data)\n        except Exception as e:\n            raise CIMDValidationError(f\"Invalid CIMD document: {e}\") from e\n\n        if str(doc.client_id).rstrip(\"/\") != client_id_url.rstrip(\"/\"):\n            raise CIMDValidationError(\n                f\"CIMD client_id mismatch: document says '{doc.client_id}' \"\n                f\"but was fetched from '{client_id_url}'\"\n            )\n\n        # Validate jwks_uri if present (SSRF check for JWKS endpoint)\n        if doc.jwks_uri:\n            jwks_uri_str = str(doc.jwks_uri)\n            try:\n                await validate_url(jwks_uri_str)\n            except SSRFError as e:\n                raise CIMDValidationError(\n                    f\"CIMD jwks_uri failed SSRF validation: {e}\"\n                ) from e\n\n        logger.info(","sourceCodeStart":397,"sourceCodeEnd":433,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/server/auth/cimd.py#L397-L433","documentation":"The fetched JSON parsed successfully but CIMDDocument.model_validate rejected it — the document violates the CIMD schema: missing required client_id or redirect_uris, uses a forbidden shared-secret token_endpoint_auth_method, has invalid URL fields, or otherwise fails Pydantic validation. fetch() wraps the Pydantic error in CIMDValidationError.","triggerScenarios":"CIMDFetcher.fetch/get_client on a document missing required fields (client_id, redirect_uris), with empty redirect_uris, with token_endpoint_auth_method='client_secret_basic'/'client_secret_post'/'client_secret_jwt', or with malformed AnyHttpUrl fields.","commonSituations":"Documents generated for classic dynamic-client-registration clients that include client_secret fields; hand-edited metadata missing redirect_uris; schema drift between CIMD draft versions; URLs written as plain strings that fail URL validation.","solutions":["Read the wrapped Pydantic message ('Invalid CIMD document: ...') to see exactly which field failed","Add required fields: client_id and at least one valid redirect_uri","Change token_endpoint_auth_method to 'none' or 'private_key_jwt' — shared-secret methods are forbidden in CIMD","Ensure all *_uri fields are absolute http(s) URLs","Re-host the corrected document (client_id must still match the hosting URL)"],"exampleFix":"// before\n{\"client_id\": \"https://app.example.com/client.json\",\n \"token_endpoint_auth_method\": \"client_secret_basic\"}\n// after\n{\"client_id\": \"https://app.example.com/client.json\",\n \"redirect_uris\": [\"https://app.example.com/callback\"],\n \"token_endpoint_auth_method\": \"private_key_jwt\",\n \"jwks_uri\": \"https://app.example.com/jwks.json\"}","handlingStrategy":"validation","validationCode":"required = {\"client_id\", \"redirect_uris\"}\ndef doc_shape_ok(d: dict) -> bool:\n    if not required.issubset(d):\n        return False\n    if not d[\"redirect_uris\"]:\n        return False\n    return d.get(\"token_endpoint_auth_method\", \"none\") in (\"none\", \"private_key_jwt\")","typeGuard":"def is_cimd_doc(obj: object) -> bool:\n    return isinstance(obj, dict) and \"client_id\" in obj and bool(obj.get(\"redirect_uris\"))","tryCatchPattern":"try:\n    doc = await fetcher.get_client(client_id)\nexcept CIMDValidationError as e:\n    # message embeds the pydantic field errors\n    return JSONResponse(400, {\"error\": \"invalid_client_metadata\", \"detail\": str(e)})","preventionTips":["Run CIMDDocument.model_validate on your JSON before hosting it","Never include shared-secret auth methods (client_secret_*) in CIMD metadata","Keep client_id and redirect_uris present and well-formed"],"tags":["oauth","cimd","pydantic","schema-validation"],"backgroundTag":"schema-validation-failed","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}