restsharp/RestSharp · error · HttpRequestException

Token request failed with status {response.StatusCode}: {bod

Error message

Token request failed with status {response.StatusCode}: {body}

What it means

Thrown by the OAuth2 endpoint authenticator when the HTTP POST to the token endpoint returns a non-success status code. The message includes the status code and the raw response body for diagnostics. Raised inside GetOrRefreshTokenAsync after reading the body.

Source

Thrown at src/RestSharp/Authenticators/OAuth2/OAuth2EndpointAuthenticatorBase.cs:91

        try {
            if (_accessToken != null && DateTimeOffset.UtcNow < _tokenExpiry)
                return _accessToken;

            var parameters = BuildRequestParameters();

            if (TokenRequest.ExtraParameters != null) {
                foreach (var kvp in TokenRequest.ExtraParameters)
                    parameters[kvp.Key] = kvp.Value;
            }

            using var content = new FormUrlEncodedContent(parameters);
            using var response = await _tokenClient.PostAsync(TokenRequest.TokenEndpointUrl, content, cancellationToken).ConfigureAwait(false);

            var body = await response.Content.ReadAsStringAsync().ConfigureAwait(false);

            if (!response.IsSuccessStatusCode)
                throw new HttpRequestException($"Token request failed with status {response.StatusCode}: {body}");

            var tokenResponse = JsonSerializer.Deserialize<OAuth2TokenResponse>(body);

            if (tokenResponse == null || string.IsNullOrEmpty(tokenResponse.AccessToken))
                throw new InvalidOperationException($"Token endpoint returned an invalid response: {body}");

            _accessToken = tokenResponse.AccessToken;
            _tokenExpiry = tokenResponse.ExpiresIn.HasValue
                ? DateTimeOffset.UtcNow.AddSeconds(tokenResponse.ExpiresIn.Value) - TokenRequest.ExpiryBuffer
                : DateTimeOffset.MaxValue;

            OnTokenResponse(tokenResponse);
            TokenRequest.OnTokenRefreshed?.Invoke(tokenResponse);

            return _accessToken;
        }
        finally {
            _lock.Release();

View on GitHub (pinned to 6a50821692)

Solutions

  1. Inspect the status code and body embedded in the exception message to identify the OAuth error (invalid_grant, invalid_client, etc.).
  2. Verify TokenRequest.TokenEndpointUrl, client credentials, and scopes are correct for the target environment.
  3. For invalid_grant due to expired refresh tokens, re-authenticate the user to obtain a fresh authorization code/refresh token.
  4. Wrap token acquisition in retry logic for transient 5xx with exponential backoff.

Example fix

// before
var authenticator = new OAuth2ClientCredentialsAuthenticator(request);

// after
try {
    await authenticator.Authenticate(client, req, ct);
} catch (HttpRequestException ex) when (ex.Message.Contains("401")) {
    // credentials invalid - surface to operator
    throw new InvalidOperationException("OAuth client credentials rejected by token endpoint", ex);
}
Defensive patterns

Strategy: try-catch

Try / catch

try { await authenticator.Authenticate(client, request, ct); } catch (HttpRequestException ex) when (ex.Message.Contains("Token request failed")) { /* inspect status/body, re-auth on invalid_grant, retry on 5xx */ }

Prevention

When it happens

Trigger: The configured TokenRequest.TokenEndpointUrl returns 4xx/5xx, e.g. invalid client credentials (401), bad grant (400), expired/revoked refresh token, network-bridged 502, or wrong token endpoint URL.

Common situations: Wrong client_id/client_secret; token endpoint URL typo or pointing to the wrong environment; refresh token revoked server-side; client credentials not granted the required scope; clock skew causing grant rejection.

Related errors


AI-assisted analysis of restsharp/RestSharp@6a50821692 (2026-08-13). Data as JSON: /api/errors/fadf6656cc747202. Report an issue: GitHub.