{"record":{"id":"21a9268999961193","repo":"restsharp/RestSharp","slug":"token-endpoint-returned-an-invalid-response-body","errorCode":null,"errorMessage":"Token endpoint returned an invalid response: {body}","messagePattern":"Token endpoint returned an invalid response: (.+?)","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/RestSharp/Authenticators/OAuth2/OAuth2EndpointAuthenticatorBase.cs","lineNumber":96,"sourceCode":"            var parameters = BuildRequestParameters();\n\n            if (TokenRequest.ExtraParameters != null) {\n                foreach (var kvp in TokenRequest.ExtraParameters)\n                    parameters[kvp.Key] = kvp.Value;\n            }\n\n            using var content = new FormUrlEncodedContent(parameters);\n            using var response = await _tokenClient.PostAsync(TokenRequest.TokenEndpointUrl, content, cancellationToken).ConfigureAwait(false);\n\n            var body = await response.Content.ReadAsStringAsync().ConfigureAwait(false);\n\n            if (!response.IsSuccessStatusCode)\n                throw new HttpRequestException($\"Token request failed with status {response.StatusCode}: {body}\");\n\n            var tokenResponse = JsonSerializer.Deserialize<OAuth2TokenResponse>(body);\n\n            if (tokenResponse == null || string.IsNullOrEmpty(tokenResponse.AccessToken))\n                throw new InvalidOperationException($\"Token endpoint returned an invalid response: {body}\");\n\n            _accessToken = tokenResponse.AccessToken;\n            _tokenExpiry = tokenResponse.ExpiresIn.HasValue\n                ? DateTimeOffset.UtcNow.AddSeconds(tokenResponse.ExpiresIn.Value) - TokenRequest.ExpiryBuffer\n                : DateTimeOffset.MaxValue;\n\n            OnTokenResponse(tokenResponse);\n            TokenRequest.OnTokenRefreshed?.Invoke(tokenResponse);\n\n            return _accessToken;\n        }\n        finally {\n            _lock.Release();\n        }\n    }\n\n    public void Dispose() {\n        if (_disposeClient) _tokenClient.Dispose();","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/restsharp/RestSharp/blob/6a5082169257438cd085f822f050d93256a8e499/src/RestSharp/Authenticators/OAuth2/OAuth2EndpointAuthenticatorBase.cs#L78-L114","documentation":"Thrown by the OAuth2 endpoint authenticator when the token endpoint returned HTTP success (2xx) but the deserialized response body either is null or has an empty AccessToken. This means the body did not conform to the expected JSON token shape even though the status code was OK.","triggerScenarios":"Token endpoint returns 200 with a body that is not valid JSON for OAuth2TokenResponse, or JSON that lacks the access_token field, e.g. an HTML login page, an error envelope, or a different field naming (access_token nested under 'data').","commonSituations":"Token endpoint URL actually points to an HTML login/consent page rather than the API token route; the IdP uses a non-standard response shape (e.g. camelCase vs snake_case mismatch); a proxy/CDN injected an HTML error page with a 200 status; mismatch between System.Text.Json default casing and the provider's casing.","solutions":["Capture the body included in the exception message and inspect its structure against OAuth2TokenResponse.","Confirm TokenEndpointUrl points to the real token API route, not a browser-facing login page.","If the provider uses different JSON casing, customize the JSON serialization or map fields accordingly.","Verify the IdP returns the token in the standard 'access_token' field."],"exampleFix":"// before\n// token endpoint returns { \"accessToken\": \"...\" } (camelCase)\n\n// after\n// ensure the endpoint returns { \"access_token\": \"...\" } (snake_case)\n// or configure a custom JSON deserializer matching the provider's contract","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { await authenticator.Authenticate(client, request, ct); } catch (InvalidOperationException ex) when (ex.Message.Contains(\"invalid response\")) { /* capture body, verify endpoint shape/casing */ }","preventionTips":["Confirm the token endpoint URL points to the API token route, not an HTML login page.","Verify the IdP returns 'access_token' in the response JSON.","Inspect the body in the exception message to detect shape/casing mismatches."],"tags":["oauth","oauth2","authentication","json","token"],"backgroundTag":null,"analyzedSha":"6a5082169257438cd085f822f050d93256a8e499","analyzedAt":"2026-08-13T20:38:25.807Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}