---
title: Error Handling & RFC 6749 Error Codes
category: Operations & Reliability
order: 12
badge: Reference
description: Comprehensive directory of OAuth 2.0 error codes, HTTP status codes, and troubleshooting recipes.
---

# Error Handling & RFC 6749 Error Codes

When an OAuth 2.0 or OpenID Connect request encounters an issue, Ternis Auth returns standardized error responses adhering to **RFC 6749 §4.1.2.1** and **§5.2**.

---

## 1. Error Response Delivery Channels

Errors are communicated through two distinct mechanisms depending on the flow phase:

1. **Redirect Errors (Authorization Endpoint)**:
   If the client provided a valid `redirect_uri`, the user's browser is redirected back to that URI with error query parameters:
   ```http
   https://app.example.com/callback?
     error=access_denied&
     error_description=The+user+denied+the+authorization+request&
     state=xyz123
   ```
2. **Direct JSON Errors (Token & API Endpoints)**:
   API endpoints return an HTTP error status code (400, 401, 403, 429) with a JSON payload:
   ```json
   {
     "error": "invalid_grant",
     "error_description": "The provided authorization code is invalid or has expired.",
     "hint": "Authorization codes expire 10 minutes after issuance."
   }
   ```

---

## 2. Standard OAuth 2.0 Error Codes

| Error Code | HTTP Status | Description & Cause | Recommended Client Action |
| :--- | :--- | :--- | :--- |
| `invalid_request` | `400` | Missing required parameters (e.g. `client_id`, `response_type`), invalid parameter values, or malformed syntax. | Verify query parameters against documentation. |
| `unauthorized_client` | `401 / 400` | The client application is not authorized to request an authorization code using this method, or client credentials failed. | Verify `client_id` and `client_secret`. |
| `access_denied` | `403` | The resource owner (user) or authorization server denied the request (e.g. user clicked "Cancel"). | Inform user that authorization was declined. |
| `unsupported_response_type` | `400` | The authorization server does not support obtaining an authorization code using this method. | Ensure `response_type=code` is sent. |
| `invalid_scope` | `400` | The requested scope is invalid, unknown, or exceeds permissions granted to the client. | Remove unauthorized scopes (e.g. `ternis:admin`). |
| `invalid_grant` | `400` | The provided authorization code or refresh token is invalid, expired, already redeemed, or the PKCE `code_verifier` did not match. | Prompt user to initiate a new authorization flow. |
| `server_error` | `500` | The authorization server encountered an unexpected condition. | Retry with exponential backoff. |
| `temporarily_unavailable` | `503` | Server is temporarily overloaded or down for maintenance. | Retry following the `Retry-After` header. |

---

## 3. Silent SSO & OIDC Specific Errors

When using `prompt=none` for silent authentication, the following errors may be returned:

| Error Code | Description |
| :--- | :--- |
| `login_required` | The user does not hold an active session on Ternis Auth. Client must redirect user for explicit login. |
| `consent_required` | The user is authenticated but has not yet consented to the requested scopes. Explicit prompt needed. |
| `interaction_required` | Multi-factor authentication (2FA) or password change is required before access can be granted. |

---

## 4. Common Developer Issues & Recipes

### Issue 1: "The redirect_uri provided is not registered"
- **Cause**: The `redirect_uri` sent in `/oauth/authorize` does not match the registered client URIs.
- **Solution**: Check protocol (`http` vs `https`), port numbers (e.g. `localhost:3000` vs `localhost:8080`), and trailing slashes. Update allowed redirect URIs in the [Account Portal](https://account.ternis.org/account/oauth-apps).

### Issue 2: "PKCE verification failed / code_verifier mismatch"
- **Cause**: The `code_verifier` sent to `/oauth/token` does not hash to the `code_challenge` sent to `/oauth/authorize`.
- **Solution**: Ensure your Base64 encoding is URL-safe (`+` -> `-`, `/` -> `_`, no padding `=`). Verify the SHA-256 algorithm was executed over raw binary bytes before Base64 encoding.

### Issue 3: Rate Limiting (`HTTP 429 Too Many Requests`)
- **Cause**: The client application exceeded rate limits on token exchange or user info endpoints.
- **Solution**: Respect the `Retry-After: <seconds>` HTTP header. Implement exponential backoff in client SDKs. Verified partners (`ternis:partner`) receive higher baseline quotas.
