{"record":{"id":"3f1d2c1bc1e64046","repo":"PrefectHQ/fastmcp","slug":"invalid-client-id","errorCode":null,"errorMessage":"Invalid client_id","messagePattern":"Invalid client_id","errorType":"http","errorClass":"AuthenticationError","httpStatus":401,"severity":"error","filePath":"fastmcp_slim/fastmcp/server/auth/auth.py","lineNumber":268,"sourceCode":"        self, request: Request\n    ) -> OAuthClientInformationFull:\n        \"\"\"Authenticate a client from an HTTP request.\n\n        Extends SDK authentication to support private_key_jwt for CIMD clients.\n        Delegates to SDK for client_secret_basic (Authorization header) and\n        client_secret_post (form body) authentication.\n        \"\"\"\n        form_data = await request.form()\n        client_id = form_data.get(\"client_id\")\n\n        # If client_id is not in form data, delegate to SDK\n        # This handles client_secret_basic which sends credentials in Authorization header\n        if not client_id:\n            return await super().authenticate_request(request)\n\n        client = await self.provider.get_client(str(client_id))\n        if not client:\n            raise AuthenticationError(\"Invalid client_id\")\n\n        # Handle private_key_jwt authentication for CIMD clients\n        if client.token_endpoint_auth_method == \"private_key_jwt\":\n            # Validate assertion parameters\n            assertion_type = form_data.get(\"client_assertion_type\")\n            assertion = form_data.get(\"client_assertion\")\n\n            if assertion_type != JWT_BEARER_ASSERTION_TYPE:\n                raise AuthenticationError(\n                    f\"Invalid client_assertion_type: expected {JWT_BEARER_ASSERTION_TYPE}\"\n                )\n\n            if not assertion or not isinstance(assertion, str):\n                raise AuthenticationError(\"Missing client_assertion\")\n\n            # Validate the JWT assertion using CIMD manager\n            try:\n                await self._cimd_manager.validate_private_key_jwt(","sourceCodeStart":250,"sourceCodeEnd":286,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/server/auth/auth.py#L250-L286","documentation":"During OAuth client authentication at the token endpoint, the provider looks up the submitted client_id via provider.get_client(); if no registered client matches, an AuthenticationError('Invalid client_id') is raised. This only happens when client_id is present in the form body; client_secret_basic (credentials in the Authorization header) is delegated to the SDK instead.","triggerScenarios":"POST to the token endpoint with client_id in form data whose value is not registered with the OAuth provider (auth.py:266-268) — e.g. client was deleted, wrong environment, or a CIMD/private_key_jwt client whose metadata URL isn't fetchable/registered.","commonSituations":"Client credentials from dev/staging used against a production server; OAuth client registration never completed or was rotated; CIMD client_id (an HTTPS URL) unreachable or mistyped; clients configured with client_secret_basic still putting client_id in the body with a mismatched secret.","solutions":["Verify the client_id sent by the OAuth client exactly matches a registered client in your provider's store.","Re-register the client (or fix the client's configuration) so get_client() returns its information.","Confirm you're hitting the right environment — registration data differs between dev/staging/prod.","For CIMD clients, ensure the client_id metadata URL is reachable and valid, or fall back to a registered client_id."],"exampleFix":"// before\n# client config\nclient_id = \"my-app\"  # not registered on this server\n\n// after\n# register first, then use the issued id\nclient_id = \"registered-client-id-from-provider\"","handlingStrategy":"validation","validationCode":"async def client_id_is_registered(provider, client_id: str) -> bool:\n    return await provider.get_client(client_id) is not None","typeGuard":null,"tryCatchPattern":"# server side (returned to client as OAuth error)\ntry:\n    client = await provider.get_client(client_id)\nexcept AuthenticationError as e:\n    return JSONResponse(status_code=401, content={'error': 'invalid_client'})","preventionTips":["Keep client registrations in sync across environments.","Use automated client registration (RFC 7591) where possible.","Log the submitted client_id (not secrets) on failure to speed diagnosis."],"tags":["oauth","authentication","client-configuration"],"backgroundTag":"invalid-client-credentials","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}