# Error codes

Every error has a `type` and a stable `code`. Branch on `code`. Read [errors](https://docs.vabu.live/concepts/errors.md) for the response shape and the retry rules. Each code below has an anchor, and `doc_url` in an error response links to it.

## Error types

| Type | HTTP | When |
|---|---|---|
| `invalid_request_error` | 400, 404, 409, 422 | Bad input, missing resource, conflict, validation |
| `authentication_error` | 401 | Missing or bad key or token |
| `permission_error` | 403 | Scope, role, or product not enabled |
| `rate_limit_error` | 429 | Limit hit |
| `idempotency_error` | 409 | Key reused with a different body, or still in flight |
| `provider_error` | 502 | An upstream provider failed |
| `api_error` | 500, 503 | Our fault |

## Codes

### idempotency_key_reused

Type `idempotency_error`, HTTP 409. You sent an `Idempotency-Key` you already used with a different method, path or body. Use a new key for a new action. See [idempotency](https://docs.vabu.live/concepts/idempotency.md).

### idempotency_key_in_use

Type `idempotency_error`, HTTP 409. A request with this key is still running. Wait a moment, then retry with the same key.

### product_not_enabled

Type `permission_error`, HTTP 403. The product behind this route is switched off for your tenant. Enable it for the environment you are calling.

## Codes by product

Each product has its own codes. New codes can appear at any time. If you meet a code you do not know, treat it as its `type`.

### Platform, Access and Streams

| Code | HTTP | When |
|---|---|---|
| <span id="insufficient_permissions"></span>`insufficient_permissions` | 403 | The key or user cannot call this endpoint. A publishable key on a secret-only route gives this. |
| <span id="test_mode_unavailable"></span>`test_mode_unavailable` | 403 | A test key called an endpoint that has no test mode yet. |
| <span id="access_denied"></span>`access_denied` | 403 | The customer has no active entitlement. `error.details.reason` says why. |
| <span id="device_limit_reached"></span>`device_limit_reached` | 403 | The entitlement's `max_devices` is used up. |
| <span id="view_limit_reached"></span>`view_limit_reached` | 403 | The entitlement's `max_views` is used up. |
| <span id="session_ended"></span>`session_ended` | 403 | A heartbeat for a session that is over. `error.details.reason` is `replaced_by_newer_session`, `missed_heartbeats`, `entitlement_inactive` or `client`. |
| <span id="concurrency_limit_reached"></span>`concurrency_limit_reached` | 409 | Another session is open and the policy is `reject_new`. |
| <span id="entitlement_revoked"></span>`entitlement_revoked` | 409 | You repeated a grant that was revoked. Grant again with a new `source_ref`. |
| <span id="invalid_state"></span>`invalid_state` | 409 | The entitlement cannot be suspended or resumed from its current state. |
| <span id="external_id_taken"></span>`external_id_taken` | 409 | Another object of this type already has this `external_id`. |
| <span id="invalid_customer_token"></span>`invalid_customer_token` | 401 | A customer token was rejected. `error.details.reason` says why. See [customer tokens](https://docs.vabu.live/concepts/customer-tokens.md#errors). |
| <span id="stream_disabled"></span>`stream_disabled` | 409 | The live stream is switched off. |
| <span id="asset_not_ready"></span>`asset_not_ready` | 409 | The asset is still processing. |
| <span id="no_playback_id"></span>`no_playback_id` | 409 | The stream or asset has no playback id. |
| <span id="signing_not_configured"></span>`signing_not_configured` | 409 | Playback signing is not set up for the account. |
| <span id="dedicated_environment_required"></span>`dedicated_environment_required` | 409 | Signing keys need an account with its own video environment. |
| <span id="resource_not_found"></span>`resource_not_found` | 404 | The stream or asset is not yours. |
| <span id="provider_rejected"></span>`provider_rejected` | 422 | The video network refused the request. `message` says why. |
| <span id="provider_error"></span>`provider_error` | 502 | The video network could not be reached. Retry. |
| <span id="validation_failed"></span>`validation_failed` | 422 | The request is invalid. `error.details` lists each field. |

Other products add their codes as they reach the API reference.
