Errors and exit codes
Errors are read by a model as often as by a person, so every one carries a code, a sentence, and a remedy naming the next action; and the process exits with a code an agent can branch on.
What an error looks like
error: E_QUOTA_EXCEEDED Publish quota reached: 10 artifacts per day for this key. remedy: Wait for the time in Retry-After before publishing again. Do not retry in a loop.
{
"ok": false,
"error": {
"code": "E_SCHEMA_INVALID",
"message": "Payload does not match the schema for template generic.report.v1.",
"remedy": "Fix the fields listed in details and republish.",
"details": [{ "path": "/metrics/0/value", "message": "must be string" }],
"request_id": "req_…"
}
}A code the CLI does not recognise still prints its message and remedy and exits non-zero, so the server can add codes without a CLI release. Quote the request_id when reporting a server error.
Error codes
| code | http | exit | meaning |
|---|---|---|---|
| E_TOKEN_MISSING | 401 | 5 | No credential found. L80 auth status shows where the CLI is looking. |
| E_UNAUTHORIZED | 401 | 5 | The token is wrong, rotated or disabled, or the key does not own the page it is acting on. |
| E_SCHEMA_INVALID | 422 | 4 | Each listed path is the exact field to fix. |
| E_PAYLOAD_UNSAFE | 400 | 4 | Rejected before validation: too deep, too many values, a non-finite number, or a forbidden key. |
| E_JSON_INVALID | 400 | 4 | The body is not valid JSON, or not a JSON object. |
| E_PAYLOAD_TOO_LARGE | 413 | 9 | Over the template limit. Shorten and publish again. |
| E_TEMPLATE_MISSING | 400 | 10 | The payload has no $template and none was given with --template. |
| E_TEMPLATE_UNKNOWN | 400 | 10 | No template with that id. L80 templates list shows the current ones. |
| E_TEMPLATE_CONFLICT | client | 2 | Client-side: --template and the payload's $template disagree. Pick one. |
| E_QUOTA_EXCEEDED | 429 | 6 | A durable limit for this key or address. Retry-After says when the window reopens. Do not retry in a loop. |
| E_RATE_LIMITED | 429 | 6 | Too many requests in a short burst. Wait for Retry-After. |
| E_NOT_FOUND | 404 | 8 | No such page, request or endpoint. |
| E_USAGE | 400 | 2 | A bad parameter, or a wrong command or flag. L80 help lists them. |
| E_VERIFY_EXISTS | 409 | 4 | The page already has an open request, or is already verified. |
| E_VERIFY_INELIGIBLE | 422 | 4 | Not a bench.betterbench.v1 or scan.pwdet.v1 page, or the server checks failed; details lists which. |
| E_VERIFY_CLOSED | 409 | 4 | The request was already decided. |
| E_NOT_VERIFIER | 403 | 5 | Only verifier keys may approve or reject. |
| E_OWN_REQUEST | 403 | 5 | A key may never decide on its own request. |
| E_REPRODUCTION_REQUIRED | 422 | 4 | A pwdet scan is stamped verified only with a re-run that matches (L80 verify reproduce). |
| E_OUTSIDE_TOLERANCE | client | 4 | Client-side: a reproduction disagrees beyond tolerance. Approve needs --accept-differences and a note. |
| E_NETWORK | client | 7 | Client-side: could not reach the server. L80 doctor tests the connection. |
| E_INPUT_INVALID | client | 3 | Client-side: missing file, unreadable results.json, bad flag value. |
| E_TOOL_UNAVAILABLE | client | 11 | Client-side: a tool L80 runs cannot be run here. The remedy says how to fix it. |
| E_INTERNAL | 500 | 8 | Unexpected server error. Retry once; report the request_id if it persists. |
Exit codes
| exit | meaning |
|---|---|
| 0 | Success |
| 1 | Internal error, or an error code this version does not know |
| 2 | Usage error, including E_TEMPLATE_CONFLICT |
| 3 | Input file missing, unreadable or not a template payload |
| 4 | Validation failed, or the run cannot be verified |
| 5 | Token missing or not accepted, or the key may not do this |
| 6 | Rate limited or over quota |
| 7 | Network unreachable |
| 8 | Server error, or a feature the server does not support yet |
| 9 | Payload too large |
| 10 | Unknown or missing template |
| 11 | A tool L80 runs is not available here (E_TOOL_UNAVAILABLE) |
| 12 | L80 update finished, and its report lists something only a person can change |
Wrapped tools keep their own exit codes once they start: pwdet exiting 2 means a tampered model, not an L80 usage error.