# Errors

Every error body is JSON. This page lists each status you can see, where you see it, and what to do.

## In the browser

The collector reports errors by throwing or by rejecting the promise from `ready()` or `verify()`:

| Error | Cause | What to do |
|---|---|---|
| `octet: invalid apiUrl "..."` | `apiUrl` is not a URL. | Set `apiUrl` to your edge's origin. |
| `octet: apiUrl must be https://...` | `apiUrl` is not `https://`. | Use `https://`. `http://` works only for `localhost`. |
| `octet: call start() before ready()` | `ready()` ran before `start()`. | Call `start()` at page load. |
| `octet: unknown mode "..."` | `mode` is not `'full'`, `'lite'` or `'passive'`. | Fix the value, or leave `mode` out to get `full`. |
| `signal report failed: <status>` | Your edge answered with an error status. | Look up the status under [From your edge](#from-your-edge). |
| `TypeError` from `fetch` | The browser could not complete the POST. Usually CORS, DNS, TLS, or the edge is down. | Check the browser console, `ALLOWED_ORIGIN`, and the edge's `/health`. |
| `AbortError` | Your code aborted the collection. | None. No verdict was produced. |

Blocked or failed measurements never cause an error. If the WebSocket to your edge fails, the collector sends what it has and results are weaker. The usual causes are a Content Security Policy without `wss://` for your edge, and networks that block WebSockets.

## From your edge

These are the responses to `POST /v1/signals`, which the browser sees:

| Status | Body | Cause | What to do |
|---|---|---|---|
| `200` | `{"ok":true}` | Octet accepted the session. | None. |
| `400` | `{"error":"read_failed"}` | The edge could not read the request body. | Retry. |
| `405` | `{"error":"method_not_allowed"}` | A method other than `POST` or `OPTIONS`. | Use `POST`. |
| `502` | `{"error":"octet_unreachable"}` | The edge could not reach Octet. | Check `OCTET_URL`, outbound TCP 443, and DNS on the edge host. With mutual TLS, check the certificate files. The edge's log has the detail. |
| Octet's status | `{"error":"octet_rejected","reason":"<reason>","status":<status>}` | Octet refused the session. The edge passes Octet's status and reason code through. | Look up the reason below. |

When Octet refuses a session, the edge logs one line with the status and reason, with no end-user data. `reason` is `unknown` when Octet's reply carries no plain reason code.

### Reasons Octet gives your edge

| Status | Reason | Cause | What to do |
|---|---|---|---|
| `401` | `missing_license` | `LICENSE` is not set on the edge. | Set `LICENSE` and restart. |
| `401` | `bad_vendor_prefix`, `malformed_token`, `bad_footer`, `bad_payload`, `bad_signature` | `LICENSE` is not a valid license token. It may be truncated, or be a read token. | Copy the license token again from Octet's email. |
| `401` | `wrong_typ`, `wrong_issuer`, `product_not_licensed`, `platform_not_licensed` | The token is valid but not an Octet Browser license. | Use the license token issued for Octet Browser. |
| `401` | `expired`, `not_yet_valid`, `missing_exp`, `missing_iat_and_nbf` | The license token is outside its validity period, or the edge host's clock is wrong. | Check the host's clock. If it is right, ask Octet for a new license token. |
| `401` | `revoked` | Octet revoked the license token. | Deploy the replacement Octet sent you, or contact Octet. |
| `401` | `unknown`, `verify_error`, `license_not_configured`, `license_keys_url_insecure` | Octet could not check the license. | Retry. If it persists, contact [developer@octetproof.com](mailto:developer@octetproof.com). |
| `400` | `invalid_json` | The body is not JSON. | Send the collector's POST unchanged. |
| `400` | `missing_fields` | The body is JSON but not a collection. An empty `{}` body gets this after a successful license check. | Send the collector's POST unchanged. |
| `413` | `payload_too_large` | The body is larger than Octet accepts. | Send the collector's POST unchanged. |

## From the Octet API

These are the responses to `GET /v1/verdict/{sessionRef}`, which your backend sees:

| Status | Body | Cause | What to do |
|---|---|---|---|
| `200` | The verdict | See [Verdict Reference](/docs/browser/reference/verdict/). | Apply your policy. |
| `404` | `{"status":"pending","ref":"..."}` | No verdict for this `sessionRef` yet, the verdict is more than 2 minutes old, the `sessionRef` is wrong, or the session arrived under another license. | Retry with `waitMs`. If it persists, check that the page passes the same `sessionRef` to `start()`. |
| `401` | `{"error":"unauthorized"}` | No `Authorization: Bearer octet_read_...` header. A license token sent as the bearer also gets this. | Send your read token. |
| `401` | `{"error":"expired"}` | The read token has expired. | Mint a new one. See [Credentials](/docs/browser/integration/credentials/). |
| `401` | `{"error":"revoked"}` | The read token, or its license, has been revoked. | Mint a new one, or contact Octet if the license was revoked. |
| `401` | `{"error":"not_yet_valid"}` | The read token isn't valid yet. | Check your server's clock. |
| `401` | `malformed_token`, `bad_footer`, `bad_payload`, `bad_signature`, `unknown_kid:...` | The read token is damaged or incomplete. | Copy it again, or mint a new one. |
| `401` | `wrong_typ`, `wrong_issuer`, `wrong_audience`, `missing_scope`, `wrong_env`, `missing_lid`, `missing_exp`, `missing_iat_and_nbf`, `unsupported_schema:...` | The token is not an Octet Browser read token. | Mint a read token in the **Read tokens** tab of your Octet Browser license. |
| `401` | `read_tokens_not_configured`, `license_keys_url_insecure`, `verify_error` | Octet could not check the read token. | Retry. If it persists, contact [developer@octetproof.com](mailto:developer@octetproof.com). |

The `401` reason codes from `GET /v1/verdict` appear exactly as listed, and some carry a suffix after a colon.

## Key set

`GET https://geo.octetproof.com/.well-known/browser-verdict-jwks.json` returns `200` with the key set. Cache it for up to 5 minutes. See [Verify the Signed Token](/docs/browser/integration/verify-token/#the-key-set).
