# Errors and troubleshooting

> Recognise every error OneiD returns, where it appears and what to change, and fix the most common integration problems.

Source: https://oltinid.com/docs/reference/errors/ · Section: Reference · All OneiD documentation: https://oltinid.com/llms.txt

OneiD reports errors with the standard OAuth 2.0 error codes. Where the error appears depends on the endpoint: at your redirect URI, as JSON from the token endpoint, or on OneiD's own error page when it cannot safely redirect. This page lists every error, then walks through common problems.

## Error response format

### Errors at your redirect URI

Errors from the authorize endpoint are sent to your redirect URI with these parameters:

| Parameter | Description |
|---|---|
| `error` | The error code, for example `access_denied`. |
| `error_description` | A human-readable explanation. Log it; do not parse it or show it to users as is. |
| `state` | The `state` you sent. Check it as you would on success. |
| `iss` | The issuer, `https://YOUR_ONEID/`. Check that it matches. |

```http
HTTP/1.1 302 Found
Location: https://app.example.com/callback?error=login_required&error_description=The+user+must+sign+in.&state=Xk3fQ9vLp2&iss=https%3A%2F%2FYOUR_ONEID%2F
```

With `response_mode=form_post`, the same parameters arrive as a posted form.

### Errors on OneiD's error page

If the `client_id` is unknown or the `redirect_uri` is not registered for the client, OneiD does not redirect to your application. It shows its own error page with `invalid_request`. Logout errors are also shown on OneiD's page; the browser is not redirected.

### Errors from the token endpoint and other back-channel endpoints

The token, introspection and revocation endpoints answer errors with a JSON body and an HTTP status:

```http
HTTP/1.1 400 Bad Request
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store

{
  "error": "invalid_grant",
  "error_description": "..."
}
```

| HTTP status | Errors |
|---|---|
| 400 | `invalid_request`, `invalid_grant`, `invalid_scope`, `unsupported_grant_type` |
| 401 | `invalid_client` |
| 429 | `slow_down` (rate limit). See [Rate limits](https://oltinid.com/docs/reference/rate-limits/). |

The body may contain other fields, such as `error_uri`. Ignore fields you do not use. Branch on `error`, never on `error_description`.

The userinfo endpoint answers a missing, expired or revoked access token with HTTP 401 and a `WWW-Authenticate: Bearer` header.

## Error codes

| Error | Where it appears | Cause | What to do |
|---|---|---|---|
| `invalid_request` | OneiD error page (authorize) | The `client_id` is unknown, or the `redirect_uri` does not exactly match one registered for the client. | Use the exact redirect URI registered for the client, or ask your administrator to register it. |
| `invalid_request` | Redirect URI or token endpoint | A required parameter is missing or malformed, for example `code_challenge`. | Fix the request. See [Endpoints](https://oltinid.com/docs/reference/endpoints/). |
| `invalid_request` | OneiD error page (logout) | `post_logout_redirect_uri` was sent with neither `id_token_hint` nor `client_id`. | Send `id_token_hint` (recommended) or `client_id`. |
| `invalid_client` | Token, introspection, revocation (HTTP 401) | Unknown client, wrong secret, disabled client, or expired secret ("The client secret has expired."). | Check the client ID and secret. Ask your administrator whether the client is enabled and the secret is current. |
| `unauthorized_client` | Authorize, logout | The client is disabled. | Ask your administrator to enable the client. |
| `invalid_grant` | Token endpoint | The code or refresh token is expired, already used or revoked; the code verifier does not match the code challenge; or the user was deleted, locked, must change their password or must enrol in MFA. | Start a new sign-in. Do not retry with the same code or refresh token. |
| `invalid_scope` | Authorize, token endpoint | The client is not allowed one of the requested scopes. | Request only allowed scopes, or ask your administrator to allow the scope for the client. |
| `unsupported_grant_type` | Token endpoint | The grant type is not supported, for example `password`. | Use `authorization_code`, `refresh_token` or `client_credentials`. |
| `access_denied` | Redirect URI | The user refused consent. | Show a calm message and let the user try again. |
| `login_required` | Redirect URI | `prompt=none` was sent and the user must sign in. | Start an interactive sign-in without `prompt=none`. |
| `consent_required` | Redirect URI | `prompt=none` was sent and the user must give consent. | Start an interactive sign-in without `prompt=none`. |
| `interaction_required` | Redirect URI | `prompt=none` was sent and the user must change their password or enrol in MFA first. | Start an interactive sign-in without `prompt=none`. |
| `request_not_supported` | Redirect URI | A `request` parameter (request object) was sent. | Send the parameters directly in the query or form. |
| `request_uri_not_supported` | Redirect URI | A `request_uri` parameter was sent. | Send the parameters directly in the query or form. |
| `slow_down` | Any rate-limited endpoint (HTTP 429) | Too many requests. | Wait for the number of seconds in `Retry-After`, then retry. |

## Troubleshooting

### OneiD shows an error page instead of returning to my application

**Symptom:** after the redirect to OneiD, the browser stays on a OneiD error page with `invalid_request`.

**Cause:** the `client_id` is unknown, or the `redirect_uri` does not exactly match one registered for the client. OneiD compares redirect URIs exactly: scheme, host, port, path and trailing slash. There are no wildcards. `https` is required except for loopback addresses (`localhost`, `127.0.0.1`, `[::1]`).

**Fix:** compare the `redirect_uri` in the request with the registered list character by character. Ask your administrator to register the exact value. See [Client settings](https://oltinid.com/docs/reference/client-settings/).

### invalid_client or unauthorized_client

**Symptom:** the token endpoint returns `invalid_client` (HTTP 401), or the authorize or logout endpoint returns `unauthorized_client`.

**Cause:** `invalid_client` means client authentication failed: unknown client ID, wrong secret, expired secret or disabled client. `unauthorized_client` at authorize and logout means the client is disabled.

**Fix:** check that you send the right client ID and secret, with `client_secret_basic` or `client_secret_post`. If the secret was replaced, use the new one. Ask your administrator whether the client is enabled and the secret has not expired.

### invalid_grant at the token endpoint

**Symptom:** exchanging a code or refreshing tokens returns `invalid_grant`.

**Cause:** one of:

- The code was already used. Codes are single-use; reloading the callback page sends the same code again.
- The code expired. Codes are valid for 5 minutes.
- The `code_verifier` does not match the `code_challenge`, often because the verifier was lost or replaced between the redirect and the callback.
- The refresh token expired, was revoked, or was used a second time after the grace period.
- The user was deleted or locked, or must change their password or enrol in MFA.

**Fix:** exchange the code once, right away, and do not reload the callback page. Keep the code verifier with the `state` until the callback. After a refresh, store the new refresh token. When `invalid_grant` persists, start a new sign-in.

### invalid_scope

**Symptom:** the authorize or token endpoint returns `invalid_scope`.

**Cause:** the client asked for a scope it is not allowed.

**Fix:** request only the scopes allowed for the client, or ask your administrator to allow the scope. API scopes such as `orders.read` must be created and allowed by an administrator first.

### access_denied

**Symptom:** the callback receives `error=access_denied`.

**Cause:** the user refused consent on the consent page.

**Fix:** handle it as a normal outcome. Explain that the application needs the permission and offer to try again.

### HTTP 429 Too Many Requests

**Symptom:** a request returns HTTP 429 with `"error": "slow_down"`.

**Cause:** the client sent too many requests in a short time.

**Fix:** wait the number of seconds in the `Retry-After` header, then retry with backoff. Cache tokens until they expire instead of requesting a new one per call. See [Rate limits](https://oltinid.com/docs/reference/rate-limits/).

### CORS error in the browser console

**Symptom:** a browser application shows a CORS error when its library calls the token, userinfo or revocation endpoint.

**Cause:** the application's origin is not registered as an allowed CORS origin on an enabled client.

**Fix:** ask your administrator to add the origin, in the form `scheme://host[:port]` with no path, to the client's allowed CORS origins. Changes take effect within about 15 seconds. Introspection never allows cross-origin requests. See [Browser applications and CORS](https://oltinid.com/docs/guides/browser-applications/).

### .NET: "Correlation failed"

**Symptom:** an ASP.NET Core application returns from OneiD and fails with "Correlation failed".

**Cause:** the application runs on plain `http`. The browser does not send back the correlation cookie that the OpenID Connect handler set before the redirect.

**Fix:** run the application on `https`, also in development, and register the `https` redirect URI for the client.

## Learn more

- [Endpoints](https://oltinid.com/docs/reference/endpoints/)
- [Rate limits](https://oltinid.com/docs/reference/rate-limits/)
- [Security best practices](https://oltinid.com/docs/guides/security-best-practices/)
