Skip to content

Native API errors

Every native API error — HTTP response or WebSocket frame — carries one structured error object. Clients should branch on code, retry when retryable is true, and treat message as human-readable text that may change between releases.

HTTP error responses wrap the error object in an envelope:

{
"error": {
"code": "op.missing_index",
"message": "no enabled index covers fields [state, rank]",
"requestId": "req-...",
"timestamp": "2026-06-10T17:03:21Z",
"severity": "error",
"retryable": false,
"detail": { "fields": ["state", "rank"] },
"remediation": {
"action": "create_index",
"message": "Create an index covering the required fields, then retry."
}
}
}

WebSocket error, op.error, and fatal_error frames embed the same error object under their error field.

FieldTypeMeaning
codestringStable machine-readable code, dot-namespaced
messagestringHuman-readable description; not stable
requestIdstringServer-assigned id for correlating logs
timestampstringRFC 3339 time the error was produced
severitystringfatal, error, or warning
retryablebooleanWhether retrying the same request can succeed
detailobject or nullCode-specific structured context; commit-path errors include retryability
remediationobjectOptional; {"action": "<verb>", "message": "..."}

Remediation action values: retry, wait_and_retry, fix_request, fix_function, reauthenticate, refresh_resource, create_index, upgrade_client, upgrade_server, contact_operator.

PrefixMeaning
auth.*Authentication and authorization
protocol.*WebSocket protocol negotiation and handshake
op.*A specific operation failed; the request itself is at fault or the target is missing
session.*Session- or tenant-level conditions
rate.*Capacity and rate limiting
runtime.*Function runtime deadlines, stalls, and execution limits
service.*Server-side infrastructure conditions
CodeStatusRetryableDetailNotes
auth.unauthorized401noMissing or invalid credential
auth.forbidden403noCredential valid, access denied
auth.permission_denied403noOperation not permitted for principal
op.invalid_input400noMalformed request payload or path value
op.cancelled408yesRequest cancelled before completion
runtime.execution_timeout408no{"timeoutKind":"execution", "timeoutMs"}Function exhausted its execution-time budget; reduce work or increase the configured limit
runtime.system_timeout408no{"timeoutKind":"system", "timeoutMs"}Function exhausted its end-to-end wall-time budget; ensure returned promises settle and background work completes within the configured limit
runtime.promise_stalled422noA returned promise cannot settle because the event loop is idle; fix the function so the promise has a reachable resolution or rejection path
op.document_not_found404no{"documentId"}
op.scheduled_job_not_found404no{"jobId"}
op.schema_not_found404no{"table"}
op.not_found404noGeneric missing resource
op.conflict409varies{"conflictingSequence"?, "attempts"?, "retryability"}Retryable optimistic conflict or terminal generic conflict
op.out_of_retention409yes{"minimumSequence"?, "retryability": "restart_transaction"}Restart from a fresh snapshot
op.cap_exceeded400no{"cap", "observed", "limit", "retryability": "terminal"}Reduce deterministic mutation usage
op.already_exists409noResource already exists
op.precondition_failed412noStale generation or resource version; refresh and retry
op.missing_index412no{"fields"}No enabled index covers the query
op.schema_validation422noDocument violates the active table schema
op.historical_readvariesvaries{"historicalReadKind"}See below
session.tenant_not_found404no{"tenantId"}
service.route_not_found404noNo such endpoint
rate.resource_exhausted429yesWait for capacity to recover
rate.overloaded429yes{"retryability": "retryable_after_backoff"}Admission capacity is temporarily exhausted
rate.committer_full429yes{"capacity", "retryability": "retryable_after_backoff"}Committer inbox is full
rate.rejected_before_execution429yes{"retryability": "retryable"}Guaranteed not to have started
rate.limited429yes{"retryAfterMs", "retryability": "retryable_after_backoff"}Tenant write-rate limit
service.storage_busy503yes{"storageKind"}
service.storage_transient503yes{"storageKind"}
service.unavailable503yes{"storageKind"}Storage backend unavailable
service.transport503yesConnection or transport failure
service.storage_io500yes{"storageKind"}
service.storage_corruption500no{"storageKind"}Severity fatal; operator intervention required
service.storage_other500no{"storageKind"}
service.serialization500no
service.internal500noSeverity fatal; the fixed public message is correlated to server diagnostics by requestId

detail.retryability is the stable instruction for commit-path failures. The top-level retryable boolean is convenient for generic clients; the detailed value tells a transaction-aware client how to retry.

ClassNative codeMeaningRetryabilityClient action
Conflictop.conflictA newer commit invalidated an observed or derived dependency.retryableRetry the complete mutation after the bounded server retry budget is exhausted.
Overloaded / committer fullrate.overloaded, rate.committer_fullA bounded server queue has no capacity.retryable_after_backoffBack off, then retry.
Rejected before executionrate.rejected_before_executionNimbus guarantees the invocation never started.retryableIt is idempotent-safe to retry immediately.
Rate limitedrate.limitedThe tenant write-rate window is full.retryable_after_backoffWait at least retryAfterMs, then retry.
Out of retentionop.out_of_retentionThe transaction snapshot is older than retained validation history.restart_transactionDiscard the transaction and restart from a fresh snapshot.
Cap exceededop.cap_exceededThe mutation deterministically exceeded a prepare-time resource cap.terminalReduce the mutation’s reads or writes; repeating the same request will fail.

Transport adapters translate these classes into their documented protocol vocabulary, but preserve the same distinction between retryable environmental conditions and terminal request errors.

The status and retryability depend on detail.historicalReadKind:

historicalReadKindStatusRetryable
unsupported_backend, unsupported_adapter501yes
policy_snapshot_missing403no
snapshot_unavailable503no
cursor_mismatch, format_mismatch, retention_expired, timestamp_out_of_range400no

Handshake violations are fatal: the server sends a fatal_error frame and closes the connection with close code 1008, using the error code as the close reason.

CodeFatalDetailTrigger
protocol.no_overlapyes (HTTP 400, pre-upgrade){"serverSupports", "clientOffered"}No supported subprotocol offered
protocol.hello_timeoutyes{"timeoutMs"}No client_hello within the timeout
protocol.invalid_jsonduring handshakeInvalid JSON; after the handshake it is a non-fatal error frame
protocol.unsupported_message_typeyes{"receivedType", "expectedType"}First frame was not client_hello
protocol.unsupported_versionyes{"receivedProtocol"}client_hello named another protocol
protocol.unsupported_binaryyesBinary frame during handshake
op.failednoSubscription registration or evaluation failed (op.error frame)
session.subscription_errornoSubscription stream error without a request_id
session.unsubscribe_failednoUnsubscribe teardown failed
auth.unauthorizednoauthenticate sent on the native route

Frame shapes are defined in the WebSocket protocol reference; endpoint behavior is in the HTTP API reference.