# Errors

> Error codes from the OAuth endpoints, the Management API, the hosted pages and the SDK, and what to do about each.

Source: https://9in.io/docs/reference/errors/

## Authorization endpoint

Returned to your `redirect_uri` as `?error=…&error_description=…&state=…` (or in the fragment for the implicit flow).

| `error` | Cause | Fix |
|---|---|---|
| `invalid_request` | A missing or malformed parameter (PKCE missing for a public client, unsupported `code_challenge_method`, …) | Read `error_description` |
| `unauthorized_client` | The application may not use this flow (e.g. implicit not turned on) | Use authorization code + PKCE, or enable the grant |
| `unsupported_response_type` | `response_type` isn't `code` (or an implicit type the app allows) | |
| `invalid_scope` | A scope the tenant doesn't know | Define it on the API |
| `invalid_target` | `audience` isn't one of your APIs | Check the API identifier |
| `access_denied` | The user declined consent, or cancelled | Let them try again |
| `login_required` | `prompt=none` and no session | Start a normal sign-in |
| `consent_required` | `prompt=none` and consent is needed | Start a normal sign-in |
| `request_not_supported` | `request` or `request_uri` was sent | Send plain parameters |

An unknown `client_id` or a `redirect_uri` that isn't registered never redirects: the user sees an error page, because sending them to an unverified URL would be unsafe.

## Token endpoint

JSON `{ "error": "…", "error_description": "…" }`, status 400 unless noted.

| `error` | Cause |
|---|---|
| `invalid_request` | Missing parameter |
| `invalid_client` (401) | Unknown client, wrong secret, or no authentication for a confidential client |
| `invalid_grant` | The code is wrong, used or expired; the PKCE verifier doesn't match; the `redirect_uri` differs; the refresh token is expired, revoked or reused; the session ended; a wrong password (password grant), or two-factor is needed |
| `unauthorized_client` | The grant isn't enabled for this application |
| `unsupported_grant_type` | Unknown `grant_type` |
| `invalid_scope` | More scopes than allowed (client credentials) or than originally granted (refresh) |
| `invalid_target` | Unknown audience |
| `access_denied` | Client credentials for an API the application hasn't been given access to |
| `authorization_pending`, `slow_down`, `expired_token` | Device flow: keep polling, poll slower, start over |

## Management API

JSON `{ "error", "error_description"?, "details"? }`. See the [Management API reference](https://9in.io/docs/reference/management-api/#errors).

## Hosted pages

What users see is translated; the codes (in the activity log and some redirects) are:

| Code | Message (English) |
|---|---|
| `invalid_credentials` | Login failed |
| `account_blocked` | Account has been blocked |
| `too_many_attempts` | Too many attempts. Please try again later. |
| `transaction_expired` | This sign-in request has expired. Please start again from the application. |
| `method_disabled` | This sign-in method is not available. |
| `registration_disabled` | Registration is not available. |
| `signups_paused` | New accounts can't be created for this application right now. (Free plan above its user limit) |
| `quota_exceeded` | Sign-in is temporarily unavailable for this application. |
| `upstream_error` | Sign-in is temporarily unavailable. (Your adapter or an identity provider failed) |
| `social_failed` | Signing in with {provider} did not complete. |
| `sms_unavailable` | We can't send a text message to this number. (Country not allowed, or SMS not available on the plan) |
| `link_invalid` | This sign-in link is invalid, has expired or was already used. |
| `invalid_code`, `code_expired` | The one-time code is wrong, or expired |

Every text can be changed per language under **Translations**.

## SDK

`NineError` codes are listed in the [SDK reference](https://9in.io/docs/reference/sdk/#nineerror-codes).
