{"record":{"id":"b9a2ba6dc828105c","repo":"BerriAI/litellm","slug":"token-endpoint-auth-method-client-secret-basic-req-b9a2ba","errorCode":null,"errorMessage":"token_endpoint_auth_method=client_secret_basic requires both client_id and client_secret","messagePattern":"token_endpoint_auth_method=client_secret_basic requires both client_id and client_secret","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"error","filePath":"litellm/proxy/_experimental/mcp_server/discoverable_endpoints.py","lineNumber":918,"sourceCode":"    # recovered from a sealed code) must authenticate the way its own registration was granted,\n    # not the way the server row is configured; callers that carry no method keep the row's method\n    # as before.\n    resolved_client_id: Final = mcp_server.client_id if mcp_server.client_id else client_id\n    resolved_client_secret: Final = mcp_server.client_secret if mcp_server.client_id else client_secret\n    resolved_auth_method: Final = (\n        mcp_server.token_endpoint_auth_method\n        if mcp_server.client_id\n        else (client_token_endpoint_auth_method or mcp_server.token_endpoint_auth_method)\n    )\n    try:\n        token_request: Final = build_upstream_oauth2_token_request(\n            mcp_server,\n            auth_method=resolved_auth_method,\n            client_id=resolved_client_id,\n            client_secret=resolved_client_secret,\n        )\n    except TokenEndpointAuthConfigError as exc:\n        raise HTTPException(status_code=400, detail=str(exc)) from exc\n\n    bridge_identity: _BridgeAuthorizationCode | None = None\n    bridge_mint_ready: _BridgeMintReady | None = None\n    bridge_upstream_refresh: SecretStr | None = None\n    bridge_upstream_scope: str | None = None\n    refresh_request_scope: str | None = None\n    is_bridge: Final = mcp_server.is_oauth_delegate and mcp_server.is_dcr_bridge\n\n    if grant_type == \"refresh_token\":\n        # Phase 1 for a bridge refresh: open the client's refresh envelope, re-validate the sealed\n        # identity, and unwrap the real upstream refresh token BEFORE building token_data, so the exchange\n        # sends the upstream token and never the envelope. A failure returns without touching the upstream.\n        if is_bridge:\n            prepared_refresh: Final = await _prepare_bridge_refresh(mcp_server, refresh_token)\n            if not isinstance(prepared_refresh, _BridgeRefreshReady):\n                return _bridge_mint_error_response(prepared_refresh)\n            bridge_mint_ready = prepared_refresh.ready\n            bridge_upstream_refresh = prepared_refresh.upstream_refresh_token","sourceCodeStart":900,"sourceCodeEnd":936,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/proxy/_experimental/mcp_server/discoverable_endpoints.py#L900-L936","documentation":"Pre-flight check for the client_secret_basic token-endpoint auth method: basic auth is mathematically impossible without both halves of the credential pair, so the request is rejected 400 before the upstream exchange. Applies to the caller-supplied client case; gateway-stored clients use their own registered method.","triggerScenarios":"Thrown at litellm/proxy/_experimental/mcp_server/discoverable_endpoints.py:918 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Provide both client_id and client_secret for client_secret_basic authentication."],"exampleFix":"Send Authorization: Basic base64(client_id:client_secret).","handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}