Skip to content
Discord Get Started

Error Code Reference

DB9 REST API errors return a JSON body with a human-readable message:

Error Response Shape
{
"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.

Two kinds of failure do not use that shape:

  • A request body that cannot be read — invalid JSON, a missing required field, a field of the wrong type, or no Content-Type: application/json header — is rejected with a plain-text body (status 400, 422 or 415, below). Do not parse these as JSON.

  • A SQL error in POST /customer/databases/{database_id}/sql is not an HTTP error. The request returns 200, with "command": "ERROR" and PostgreSQL’s message and SQLSTATE in error:

    SQL error (status 200)
    {
    "columns": [],
    "rows": [],
    "row_count": 0,
    "command": "ERROR",
    "error": "ERROR: syntax error at or near \"SELEC\" | sqlstate: 42601"
    }

    Check command (or the presence of error) on every SQL response.

The request succeeded. The response body contains the requested resource or operation result.

Example
{
"id": "db_01h9xxxxxxxxxxxxxxxx",
"name": "myapp",
"state": "ACTIVE"
}

The request body is not valid JSON, or a field holds a value the endpoint rejects.

Example
{
"message": "Provide non-empty 'query' or 'file_content'"
}
Common causeResolution
Body is not valid JSON — the response is plain text, starting Failed to parse the request body as JSON:Fix the JSON syntax
SQL execution with neither query nor file_content non-emptySend the SQL in one of them. If both are set, query is run and file_content is ignored
Invalid scope_json formatEnsure the value is a valid JSON string, not an object

The request has no Authorization header, the token is expired, or the token is invalid.

Example
{
"message": "Invalid or expired token"
}
Common causeResolution
Missing Authorization: Bearer <token> header (Authorization header required. Use Bearer <token>.)Add the header to your request
Token has expiredCreate 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 mismatchVerify anonymous_secret matches the value returned at registration

The token is valid but lacks the scope required to perform the operation.

Example
{
"message": "token does not have access to this database"
}
Common causeResolution
Token scoped to specific databases, accessing anotherCheck scope_json on the token — create a new token with broader scope if needed
Read-only token attempting a write operationCreate a token without the ro access restriction

The requested resource does not exist, or the authenticated customer does not own it.

Example
{
"message": "Database not found"
}
Common causeResolution
Database ID typo or copy-paste errorDouble-check the database_id in your request path
Database was deletedCheck your database list with GET /customer/databases
Resource belongs to a different accountEnsure you are using the correct API token
Key or run ID from a different databaseVerify all IDs are from the same database

The operation conflicts with existing state — typically a duplicate name or a state precondition.

Example
{
"message": "Database name already exists for this account"
}
Common causeResolution
Creating a database/branch with a name that already existsChoose a different name or delete the existing resource first
Applying a migration that was already appliedCheck applied migrations with GET /customer/databases/{id}/migrations
Creating a secret that already existsUse PUT to update an existing secret, not POST
Adopting a database already owned by your accountThe database is already in your account — no action needed

The request has a body but no Content-Type: application/json header. The response is plain text: Expected request with `Content-Type: application/json` . Add the header.

The request is syntactically valid but semantically incorrect — the server understands the request but cannot process it.

Example (plain text)
Failed to deserialize the JSON body into the target type: missing field `name` at line 1 column 2
Common causeResolution
Missing required field — missing field `name` Check the endpoint’s field table and include all required fields
Field of the wrong type — invalid type: integer `123`, expected a stringVerify your request body matches the documented types
Invalid cron expression in function deployValidate 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 configEnsure the URL returns a valid JWKS JSON document
snapshot_at timestamp outside available history windowUse a more recent timestamp for point-in-time branching

The request was rate limited. Slow down and retry after the indicated delay.

Example
{
"message": "rate limit exceeded, retry after 30 seconds"
}
Common causeResolution
Too many anonymous account registrations from one IPWait before registering more anonymous accounts
Function invocation rate limitAdd a delay between invocations or reduce call frequency
Burst of management API requestsImplement exponential backoff with jitter

The Retry-After response header (when present) indicates the number of seconds to wait before retrying.

An unexpected error occurred on the DB9 servers.

Example
{
"message": "internal server error"
}
Common causeResolution
Transient server errorRetry the request with exponential backoff
Persistent 500 on a specific operationContact support via Discord with the request details
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;
}
}
Terminal
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"
fi