Error Code Reference
All DB9 REST API errors return a consistent JSON shape with a human-readable message:
{ "message": "human-readable message describing what went wrong"}Use the HTTP status code for programmatic error handling. Use message for displaying messages to users or for debugging.
Status Codes
Section titled “Status Codes”200 OK
Section titled “200 OK”The request succeeded. The response body contains the requested resource or operation result.
{ "id": "db_01h9xxxxxxxxxxxxxxxx", "name": "myapp", "state": "ready"}400 Bad Request
Section titled “400 Bad Request”The request body is missing required fields, contains invalid values, or is malformed JSON.
{ "message": "field 'name' is required"}| Common cause | Resolution |
|---|---|
| Missing required field | Check the endpoint’s field table and include all required fields |
| Invalid field type (e.g. string where array expected) | Verify your request body matches the documented types |
Providing both query and file_content in SQL execution | Provide only one |
Invalid scope_json format | Ensure the value is a valid JSON string, not an object |
401 Unauthorized
Section titled “401 Unauthorized”The request has no Authorization header, the token is expired, or the token is invalid.
{ "message": "invalid or expired token"}| Common cause | Resolution |
|---|---|
Missing Authorization: Bearer <token> header | Add the header to your request |
| Token has expired | Create a new token with db9 token create or POST /customer/tokens |
| Wrong token (e.g. publishable key used for management API) | Use your API token (DB9_API_KEY), not a publishable or service key |
| Anonymous secret mismatch | Verify anonymous_secret matches the value returned at registration |
403 Forbidden
Section titled “403 Forbidden”The token is valid but lacks the scope required to perform the operation.
{ "message": "token does not have access to this database"}| Common cause | Resolution |
|---|---|
| Token scoped to specific databases, accessing another | Check scope_json on the token — create a new token with broader scope if needed |
| Read-only token attempting a write operation | Create a token without the ro access restriction |
404 Not Found
Section titled “404 Not Found”The requested resource does not exist, or the authenticated customer does not own it.
{ "message": "database not found"}| Common cause | Resolution |
|---|---|
| Database ID typo or copy-paste error | Double-check the database_id in your request path |
| Database was deleted | Check your database list with GET /customer/databases |
| Resource belongs to a different account | Ensure you are using the correct API token |
| Key or run ID from a different database | Verify all IDs are from the same database |
409 Conflict
Section titled “409 Conflict”The operation conflicts with existing state — typically a duplicate name or a state precondition.
{ "message": "database with this name already exists"}| Common cause | Resolution |
|---|---|
| Creating a database/branch with a name that already exists | Choose a different name or delete the existing resource first |
| Applying a migration that was already applied | Check applied migrations with GET /customer/databases/{id}/migrations |
| Creating a secret that already exists | Use PUT to update an existing secret, not POST |
| Adopting a database already owned by your account | The database is already in your account — no action needed |
422 Unprocessable Entity
Section titled “422 Unprocessable Entity”The request is syntactically valid but semantically incorrect — the server understands the request but cannot process it.
{ "message": "SQL syntax error at position 14: unexpected token 'FORM'"}| Common cause | Resolution |
|---|---|
SQL syntax error in POST /sql or POST /migrations | Fix the SQL — the error field contains PostgreSQL’s error message |
| Invalid cron expression in function deploy | Validate the cron string (e.g. use crontab.guru) |
| Quota exceeded (databases, branches, keys) | Check your plan limits or delete unused resources |
| Invalid JWKS URL in auth config | Ensure the URL returns a valid JWKS JSON document |
snapshot_at timestamp outside available history window | Use a more recent timestamp for point-in-time branching |
429 Too Many Requests
Section titled “429 Too Many Requests”The request was rate limited. Slow down and retry after the indicated delay.
{ "message": "rate limit exceeded, retry after 30 seconds"}| Common cause | Resolution |
|---|---|
| Too many anonymous account registrations from one IP | Wait before registering more anonymous accounts |
| Function invocation rate limit | Add a delay between invocations or reduce call frequency |
| Burst of management API requests | Implement exponential backoff with jitter |
The Retry-After response header (when present) indicates the number of seconds to wait before retrying.
500 Internal Server Error
Section titled “500 Internal Server Error”An unexpected error occurred on the DB9 servers.
{ "message": "internal server error"}| Common cause | Resolution |
|---|---|
| Transient server error | Retry the request with exponential backoff |
| Persistent 500 on a specific operation | Contact support via Discord with the request details |
Handling Errors in Code
Section titled “Handling Errors in Code”TypeScript
Section titled “TypeScript”import { createDb9Client } from 'get-db9';
const client = createDb9Client();
try { const db = await client.databases.create({ name: 'myapp' });} catch (err) { if (err.status === 409) { // Database already exists — retrieve it instead const list = await client.databases.list(); const existing = list.databases.find(d => d.name === 'myapp'); } else if (err.status === 429) { // Rate limited — implement retry logic console.error('Rate limited:', err.message); } else { throw err; }}response=$(curl -s -w "\n%{http_code}" \ -H "Authorization: Bearer $DB9_API_KEY" \ -X POST https://api.db9.ai/customer/databases \ -H "Content-Type: application/json" \ -d '{"name": "myapp"}')
body=$(echo "$response" | head -1)status=$(echo "$response" | tail -1)
if [ "$status" = "409" ]; then echo "Database already exists"elif [ "$status" = "201" ] || [ "$status" = "200" ]; then echo "Created: $body"else echo "Error $status: $body"fiNext Steps
Section titled “Next Steps”- REST API Reference — all endpoints with request/response examples
- TypeScript SDK — typed client with built-in error handling
- CLI Reference — command-line interface