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. |
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. |
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. | 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. |
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. |
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.