PrefectHQ/fastmcp · error · ValueError

Client must have CIMD document for private_key_jwt

Error message

Client must have CIMD document for private_key_jwt

What it means

`CIMDClientManager.validate_private_key_jwt` requires the client object to carry a loaded CIMD document (`client.cimd_document`) before it can validate a private_key_jwt assertion. If the attribute is missing or falsy, there is no metadata containing the client's public keys, so validation cannot proceed and the library raises ValueError.

Source

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

        assertion: str,
        client,  # OAuthProxyClient, untyped to avoid circular import
        token_endpoint: str,
    ) -> bool:
        """Validate JWT assertion for private_key_jwt auth.

        Args:
            assertion: JWT assertion string from client
            client: OAuth proxy client (must have cimd_document)
            token_endpoint: Token endpoint URL for aud validation

        Returns:
            True if assertion is valid

        Raises:
            ValueError: If client doesn't have CIMD document or validation fails
        """
        if not hasattr(client, "cimd_document") or not client.cimd_document:
            raise ValueError("Client must have CIMD document for private_key_jwt")

        cimd_doc = client.cimd_document
        if cimd_doc.token_endpoint_auth_method != "private_key_jwt":
            raise ValueError("CIMD document must specify private_key_jwt auth method")

        return await self._assertion_validator.validate_assertion(
            assertion, client.client_id, token_endpoint, cimd_doc
        )

View on GitHub (pinned to 1f02114297)

Solutions

  1. Ensure the client_id resolves to a valid CIMD document and that it is loaded before authentication (fix the CIMD URL / re-trigger discovery)
  2. If the client is not CIMD-registered, use the auth method actually configured for it instead of private_key_jwt
  3. Check server logs/upstream fetch for the earlier CIMD-document load failure and correct the root cause
  4. Register the client's metadata in a reachable CIMD document containing its public keys

Example fix

# before: client without loaded metadata sending private_key_jwt
# after: point client_id at a valid CIMD document
client_id = "https://client.example.com/client-metadata.json"  # must fetch and expose cimd_document
Defensive patterns

Strategy: validation

Validate before calling

if not getattr(client, "cimd_document", None):
    raise RuntimeError("Client CIMD document not loaded; cannot use private_key_jwt")

Type guard

def has_cimd_document(client) -> bool:
    doc = getattr(client, "cimd_document", None)
    return bool(doc)

Try / catch

try:
    await manager.validate_private_key_jwt(assertion, client, endpoint)
except ValueError as e:
    if "must have CIMD document" in str(e):
        await manager.reload_client_metadata(client.client_id)
    raise

Prevention

When it happens

Trigger: `authenticate_request` reaches `validate_private_key_jwt` with a client whose `cimd_document` was never fetched, failed to load, or was set to None — e.g. the client_id's CIMD metadata retrieval failed earlier or the client is not a CIMD-registered client at all.

Common situations: Client is registered via a non-CIMD flow (standard dynamic/registered client) but sends private_key_jwt; the CIMD URL for the client_id is unreachable or invalid so the document was never loaded; the document cache was cleared and re-fetch failed.

Related errors


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