restsharp/RestSharp · error · HttpRequestException

Token request failed with status

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.

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.

Appendix: 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)