PrefectHQ/fastmcp · error · CIMDValidationError

Invalid CIMD document: {e}

Error message

Invalid CIMD document: {e}

What it means

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.

Source

Thrown at fastmcp_slim/fastmcp/server/auth/cimd.py:415

                        must_revalidate=policy.must_revalidate,
                    ),
                )
            else:
                self._remove_cache_entry(client_id_url)
            return cached.doc

        now = time.time()
        policy = self._parse_cache_policy(response.headers, now)

        try:
            data = json.loads(response.content)
        except json.JSONDecodeError as e:
            raise CIMDValidationError(f"CIMD document is not valid JSON: {e}") from e

        try:
            doc = CIMDDocument.model_validate(data)
        except Exception as e:
            raise CIMDValidationError(f"Invalid CIMD document: {e}") from e

        if str(doc.client_id).rstrip("/") != client_id_url.rstrip("/"):
            raise CIMDValidationError(
                f"CIMD client_id mismatch: document says '{doc.client_id}' "
                f"but was fetched from '{client_id_url}'"
            )

        # Validate jwks_uri if present (SSRF check for JWKS endpoint)
        if doc.jwks_uri:
            jwks_uri_str = str(doc.jwks_uri)
            try:
                await validate_url(jwks_uri_str)
            except SSRFError as e:
                raise CIMDValidationError(
                    f"CIMD jwks_uri failed SSRF validation: {e}"
                ) from e

        logger.info(

View on GitHub (pinned to 1f02114297)

Solutions

  1. Read the wrapped Pydantic message ('Invalid CIMD document: ...') to see exactly which field failed
  2. Add required fields: client_id and at least one valid redirect_uri
  3. Change token_endpoint_auth_method to 'none' or 'private_key_jwt' — shared-secret methods are forbidden in CIMD
  4. Ensure all *_uri fields are absolute http(s) URLs
  5. Re-host the corrected document (client_id must still match the hosting URL)

Example fix

// before
{"client_id": "https://app.example.com/client.json",
 "token_endpoint_auth_method": "client_secret_basic"}
// after
{"client_id": "https://app.example.com/client.json",
 "redirect_uris": ["https://app.example.com/callback"],
 "token_endpoint_auth_method": "private_key_jwt",
 "jwks_uri": "https://app.example.com/jwks.json"}
Defensive patterns

Strategy: validation

Validate before calling

required = {"client_id", "redirect_uris"}
def doc_shape_ok(d: dict) -> bool:
    if not required.issubset(d):
        return False
    if not d["redirect_uris"]:
        return False
    return d.get("token_endpoint_auth_method", "none") in ("none", "private_key_jwt")

Type guard

def is_cimd_doc(obj: object) -> bool:
    return isinstance(obj, dict) and "client_id" in obj and bool(obj.get("redirect_uris"))

Try / catch

try:
    doc = await fetcher.get_client(client_id)
except CIMDValidationError as e:
    # message embeds the pydantic field errors
    return JSONResponse(400, {"error": "invalid_client_metadata", "detail": str(e)})

Prevention

When it happens

Trigger: 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.

Common situations: 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.

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


AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29). Data as JSON: /api/errors/cc9d57cfad81ddc4. Report an issue: GitHub.