reference · errors
Error reference
Every non-2xx response from the OriginChain API has a JSON body with a stable error code, a human-readable message, and a retry flag that tells you whether the SDK should retry automatically.
// Every error response looks like this:
{
"error": "schema_not_found",
"message": "no schema registered under 'shop.orders'",
"retry": false
}
Switch on the error code in your application, not on the message - codes are stable across versions; messages are tuned for humans and may change.
Client errors (4xx).
Your request was malformed, unauthorized, or referred to something that doesn't exist. Fix the request; don't retry blindly.
| Code | HTTP | What it means | How to fix |
|---|---|---|---|
| invalid_body | 400 | Request body couldn't be parsed. | Check Content-Type matches the body (application/json for JSON, text/plain for TOML schemas, application/x-ndjson for streaming inserts). |
| type_mismatch | 400 | A column value doesn't match the declared column type. | Check the error message - it names the offending field. Common: sending a string for an i64 column, or a number for a str. |
| missing_required | 400 | A column declared `required = true` was omitted from a row write. | Send a value for every required column. Schema reference shows which columns are required. |
| fk_violation | 400 | A foreign key references a row that doesn't exist. | Insert the target row first, or remove the foreign-key constraint if you really want orphan references. |
| check_violation | 400 | A row failed a CHECK constraint. | Inspect the row's values against the constraint expression. The error message names the failing constraint. |
| dim_mismatch | 400 | A vector's length doesn't match the table's locked dim. | Every vector in a table must have the same dim. The first put sets it. |
| metric_mismatch | 400 | A vector put used a different metric than the table's locked metric. | Pick one of cosine / dot / l2 / manhattan and use it for every put + topk on the table. |
| unsupported_sql | 400 | The SQL statement contains a construct that isn't yet implemented. | See SQL reference for the supported surface. Common: ORDER BY, HAVING, OR in WHERE, window functions, CTEs. |
| validation_failed | 400 | Generic catch-all for malformed input. | Read the message field - it always names the specific problem. |
| unauthorized | 401 | Missing, malformed, or unknown bearer token. | Check your Authorization header. See Auth reference. |
| forbidden | 403 | Token valid but doesn't have access to this resource. | Usually means the token belongs to a different instance. Check endpoint hostname matches the token. |
| addon_required | 402 | Endpoint requires a paid add-on that isn't enabled. | Enable the add-on in the dashboard, or call the alternative endpoint that doesn't need it. |
| schema_not_found | 404 | No schema is registered under the given name. | Register the schema first - POST /v1/tenants/:t/schemas with the TOML manifest. |
| row_not_found | 404 | GET /rows/:schema/:pk for a primary key that doesn't exist. | Verify the pk. If the row was deleted, this is the expected response. |
| conflict | 409 | ?expect=insert was set and the row already exists. | Either drop the expect param (will overwrite) or update via the normal write path. |
| rate_limited | 429 | Per-key request budget exceeded. | Honor the Retry-After header. See Rate limits reference. |
Server errors (5xx).
Something went wrong on our side. Retry with exponential backoff. The SDKs do this automatically (up to 3 attempts by default).
| Code | HTTP | What it means | How to fix |
|---|---|---|---|
| internal_error | 500 | Server-side bug - the engine hit something it didn't expect. | Retry once. If it persists, file a support ticket with the X-OC-Trace-Id from the response headers. |
| service_unavailable | 503 | The engine is temporarily unable to serve the request (often during failover or migration). | Retry with exponential backoff. The SDKs do this automatically up to 3 retries. |
| gateway_timeout | 504 | Upstream timeout (replication ack didn't arrive in budget). | Retry. If persistent, check the instance's replication health in the dashboard. |
Retry strategy.
The SDKs already implement the right policy. If you're using raw HTTP, follow the same pattern:
- 429: read the
Retry-Afterheader (seconds), wait that long, retry. - 500, 502, 503, 504: exponential backoff (0.25s, 0.5s, 1s, 2s, capped at 4s). Maximum 3 retries.
- All 4xx except 429: do not retry. The request is malformed; retrying won't help.
- Idempotency: the SDKs auto-attach an
Idempotency-Keyheader on every mutating call, so retries don't double-insert.
For implementation details, see Rate limits.