{"record":{"id":"85dd1df81cfc67c8","repo":"PrefectHQ/fastmcp","slug":"cimd-document-is-not-valid-json-e","errorCode":null,"errorMessage":"CIMD document is not valid JSON: {e}","messagePattern":"CIMD document is not valid JSON: (.+?)","errorType":"validation","errorClass":"CIMDValidationError","httpStatus":null,"severity":"error","filePath":"fastmcp_slim/fastmcp/server/auth/cimd.py","lineNumber":410,"sourceCode":"                        doc=cached.doc,\n                        etag=policy.etag or cached.etag,\n                        last_modified=policy.last_modified or cached.last_modified,\n                        expires_at=policy.expires_at,\n                        freshness_lifetime=policy.freshness_lifetime,\n                        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:","sourceCodeStart":392,"sourceCodeEnd":428,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/server/auth/cimd.py#L392-L428","documentation":"After a successful fetch, the response body must be a JSON object representing the CIMD client metadata document. If json.loads fails (malformed, empty, HTML error page, trailing garbage), fetch() raises CIMDValidationError explaining the body is not valid JSON.","triggerScenarios":"The URL serving the client_id returns non-JSON content: an HTML 404/login page with status 200, empty body, truncated response, or JSON with syntax errors.","commonSituations":"Client hosts metadata behind an auth wall returning an HTML page; CDN/error pages served with 200 status; file uploaded with BOM or editor artifacts; wrong Content-Type with HTML fallback content.","solutions":["Open the client_id URL and confirm it returns raw JSON (application/json) with a 200 status","Fix the hosted document's JSON syntax or re-upload without BOM/trailing commas","Ensure hosting doesn't return an HTML interstitial (login/consent/captcha) for server requests","Catch CIMDValidationError and return invalid_client to the requesting party"],"exampleFix":"try:\n    doc = await fetcher.get_client(client_id)\nexcept CIMDValidationError as e:\n    if \"not valid JSON\" in str(e):\n        logger.error(\"CIMD URL %s does not serve JSON\", client_id)\n    raise","handlingStrategy":"validation","validationCode":"import json, httpx\nasync def serves_json(client_id_url: str) -> bool:\n    r = await client.get(client_id_url)\n    if \"json\" not in r.headers.get(\"content-type\", \"\"):\n        return False\n    try:\n        json.loads(r.content)\n        return True\n    except json.JSONDecodeError:\n        return False","typeGuard":"def is_json_object(body: bytes) -> bool:\n    try:\n        return isinstance(json.loads(body), dict)\n    except (json.JSONDecodeError, UnicodeDecodeError):\n        return False","tryCatchPattern":"try:\n    doc = await fetcher.get_client(client_id)\nexcept CIMDValidationError as e:\n    if \"not valid JSON\" in str(e):\n        raise InvalidClientError(\"metadata endpoint does not serve JSON\") from e\n    raise","preventionTips":["Serve the document with Content-Type: application/json and no auth interstitial","Validate JSON syntax before publishing; avoid BOM and trailing commas","Curl the URL from the server host to confirm what it actually returns"],"tags":["oauth","cimd","json","validation"],"backgroundTag":"invalid-json-response","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}