OAuth 2.0 Error Codes

All OAuth 2.0 and OpenID Connect error codes with description and spec source.

Searchable reference for OAuth 2.0 and OpenID Connect error codes across authorization, token, resource-server and device-flow endpoints, with the meaning and RFC source of each. It runs free in your browser on Gera Tools, with nothing uploaded.

Last updated Source: Gera Tools

What does invalid_grant mean in OAuth?

invalid_grant is returned by the token endpoint when the authorization code or refresh token is expired, revoked, already used, or does not match the client or redirect URI. It usually means the client must restart the authorization flow.

OAuth 2.0 and OpenID Connect error codes

OAuth 2.0 and OpenID Connect define a compact set of machine-readable error codes returned when something goes wrong at the authorization, token, resource-server, or device-flow endpoints. Each error value (paired with an optional error_description and error_uri) tells the client precisely what failed — a malformed request, a bad client credential, an expired grant, or a user interaction requirement. Knowing the exact meaning of each code, and which endpoint it comes from, collapses hours of integration debugging into minutes.

Error response shapes by endpoint

Authorization endpoint

Errors at the authorization endpoint are delivered as redirect responses — the server redirects back to the client’s redirect_uri with query parameters (for response_type=code) or fragment parameters (for implicit flows):

https://client.example.com/callback?
  error=access_denied
  &error_description=The+user+denied+access
  &state=abc123

Codes here include access_denied, unsupported_response_type, invalid_scope, and temporarily_unavailable.

Token endpoint

Errors at the token endpoint are JSON body responses, typically with HTTP 400 Bad Request:

{
  "error": "invalid_grant",
  "error_description": "The authorization code has expired."
}

The exception is invalid_client, which returns HTTP 401 Unauthorized (with a WWW-Authenticate: Basic header if the client used HTTP Basic auth).

Resource server

Resource servers return errors via the WWW-Authenticate header in HTTP 401 or 403 responses, per RFC 6750:

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="example",
                  error="invalid_token",
                  error_description="The access token has expired"

Device flow (RFC 8628)

The device authorization server uses token-endpoint polling responses with codes like authorization_pending and slow_down to manage the polling loop.

The most commonly confused code pairs

invalid_client vs invalid_grant

ErrorMeaningHTTP statusFix
invalid_clientClient authentication itself failed — bad client_id, wrong secret, or unsupported auth method401Configuration problem; check your client credentials
invalid_grantThe grant (auth code or refresh token) is expired, revoked, used, or mismatched400Restart the auth flow; do not retry the same grant

These two are the most commonly misdiagnosed. invalid_client is a server-side or configuration issue; invalid_grant is a flow-state issue.

These three OpenID Connect errors all occur when a client requests prompt=none (silent authentication) but the server cannot satisfy the request silently:

  • login_required — the user is not authenticated at all. Redirect to an interactive login.
  • consent_required — the user is authenticated but has not consented to the requested scopes. Redirect with prompt=consent.
  • interaction_required — some other interaction is needed (for example, MFA, terms acceptance). Redirect without prompt=none.

authorization_pending vs slow_down

Both appear in the device flow polling loop at the token endpoint:

  • authorization_pending — the user has not yet approved on their other device. Keep polling at the current interval.
  • slow_down — you are polling too fast. Add 5 seconds to your current polling interval and keep polling. Failure to slow down may result in access_denied.

Practical debugging checklist

  1. Which endpoint returned the error? Authorization redirect vs token JSON vs resource WWW-Authenticate — the endpoint tells you where to look.
  2. Is it invalid_client (configuration) or invalid_grant (flow state)?
  3. For OIDC silent flows: is the user not logged in (login_required) or logged in but requiring interaction (interaction_required, consent_required)?
  4. In device flow: are you slowing down on slow_down, and stopping entirely on expired_token?
  5. For insufficient_scope: the WWW-Authenticate header should name the required scope — request it in a new authorization flow.