Error Codes
OcaltQL surfaces errors two ways: standard HTTP status codes for the response itself, and a dedicated E-series code for the specific failure inside CATCH ERROR. See Error Reporting & Catching for the full CATCH ERROR mechanism.
HTTP Status Codes
Set directly with STATUS n, or implicitly by certain verbs. These govern the response itself, independent of any OcaltQL-specific error code.
| Code |
Meaning |
Typical cause in OcaltQL |
| 200 | OK | Default success status |
| 201 | Created | ACCOUNT REGISTER succeeding |
| 302 | Found (redirect) | REDIRECT "url" AS "302" |
| 401 | Unauthorized | Invalid ACCOUNT LOGIN credentials, failed ACCOUNT COMPARE |
| 404 | Not Found | ACCOUNT DELETE on a non-existent account, unresolved routes |
| 409 | Conflict | Duplicate email on ACCOUNT REGISTER/UPDATE EMAIL |
| 429 | Too Many Requests | Daily query quota exceeded — see Quotas & Pricing |
| 500 | Internal Server Error | Uncaught FATAL runtime error |
OcaltQL Error Codes (E-Series)
Every value captured by CATCH ERROR SET ?err includes an ?err("code") field from this table, alongside ?err("message") and ?err("verb"). Codes are grouped by domain — the first digit identifies the category.
E1xxx — Authentication & Accounts
| Code |
Meaning |
| E1001 | Invalid credentials on ACCOUNT LOGIN |
| E1002 | Email already registered on ACCOUNT REGISTER |
| E1003 | Account not found |
| E1004 | Session token invalid or expired |
| E1005 | New email already in use on ACCOUNT UPDATE EMAIL |
E2xxx — Filesystem
| Code |
Meaning |
| E2001 | File not found |
| E2002 | Path outside /root or /mounted |
| E2005 | Path is not under /root, /mounted or a bound /external |
E3xxx — Database
| Code |
Meaning |
| E3001 | Database does not exist |
| E3002 | Table does not exist |
| E3003 | UNIQUE constraint violated on insert/update |
| E3004 | REQUIRED column missing on insert, with no default |
| E3005 | Row not found for WHERE clause on an update/delete expecting one |
E4xxx — Network & Fetch
| Code |
Meaning |
| E4001 | FETCH/CURL connection failed or timed out |
| E4002 | Remote host returned a non-2xx status |
| E4003 | Invalid URL |
| E4004 | WEBHOOK RECEIVE rejected an unsigned or incorrectly-signed request |
E5xxx — Runtime & Execution
| Code |
Meaning |
| E5001 | Syntax error — script failed to parse |
| E5002 | Undefined operation referenced by RUN |
| E5003 | Type mismatch on a typed parameter (WITH ?x AS NUMBER REQUIRED) |
| E5004 | WebAssembly/SSH remote execution failed — see ?result("stderr")/?result("exit_code") |
E6xxx — GeoIP & DNS
| Code |
Meaning |
| E6001 | Invalid IP address supplied to GEOIP |
| E6002 | No GeoIP record for that IP — private, reserved, or absent from the database |
| E6003 | GeoIP database unavailable |
| E6004 | No visitor IP in context — the bare GEOIP forms require Site Mode |
| E6005 | Invalid domain name supplied to DNS |
| E6006 | Unknown DNS record type |
| E6007 | DNS resolution failed — no records, NXDOMAIN, or resolver unreachable |
E7xxx — Custom Query
| Code |
Meaning |
| E7001 | Query phrase word is empty — nothing to register it under |
| E7002 | A matched phrase runs out — a later word continues no registered path. A first word that matches nothing is a FATAL unrecognized verb instead, not this code |
| E7003 | Ambiguous phrase match — a SKIPPABLE node makes more than one path valid |
| E7004 | CASE must be "sensitive" or "insensitive" |
E8xxx — Object Oriented Programming
| Code |
Meaning |
| E8001 | No class of that name has been declared |
| E8002 | A class inherits in a circle, or its parent does not exist |
| E8003 | A REQUIRED property was not supplied at SPAWN |
| E8004 | A property value does not fit its declared type |
| E8005 | CALL ... ON was given something other than an instance |
| E8006 | The class has no method of that name |
Uncatchable (FATAL) States
A small number of failures are deliberately not catchable by OR CATCH ERROR — they represent a genuine script-authoring mistake, not a runtime condition to recover from gracefully.
| Cause |
Why it is FATAL |
Indexing into a multivariable without COLLAPSE first | The value has no single element to index — this is a script logic error, documented on Multivariables & Parallel Execution |
| A first word that is neither a verb nor a registered query phrase | Reported as Unrecognized verb near '…'. Custom phrases are resolved at runtime, but a word that names nothing at all is still a script-authoring mistake — see Custom Query Programming |
WAIT FOR with no timeout, unresolved past 300 seconds | The hard execution ceiling — always specify a timeout on WAIT FOR to receive a catchable result instead |
Handling Errors
FILE READ "/root/missing.txt" SET ?data OR CATCH ERROR SET ?err
AFTER IF ?err IS NOT NULL
OPEN
EMIT ?err("code") & ": " & ?err("message") & " (verb: " & ?err("verb") & ")"
CLOSE