Error contract version: 2026-06-02 (also sent on the Ablo-Version response header).
Every error — over HTTP or WebSocket — carries the same envelope:
{
"type": "AbloValidationError",
"code": "invalid_body",
"message": "The request body was missing, unparseable, or the wrong shape.",
"doc_url": "https://docs.abloatai.com/errors#invalid_body",
"request_id": "req_8f3a…"
}
type is the coarse class (catch with instanceof, or switch on it); code is the stable machine identifier documented below; request_id correlates to your server logs. Some errors carry extra structured fields (e.g. a schema push adds warnings).
retryable indicates whether the same request can succeed on a later attempt without changing anything — transient transport/lease failures are retryable; validation and permission errors are not.
Authentication
Missing, invalid, revoked, or expired credentials. Re-authenticate.
api_key_required
HTTP 401 · not retryable
This operation requires an API key.
apikey_expired
HTTP 401 · not retryable
API key has expired.
apikey_invalid
HTTP 401 · not retryable
API key is unknown or malformed.
apikey_missing
HTTP 401 · not retryable
No API key was supplied on the request.
apikey_revoked
HTTP 401 · not retryable
API key has been revoked.
auth_no_credentials
HTTP 401 · not retryable
No recognized authentication credential was presented — no API key and no bearer JWT. Send Authorization: Bearer <token>.
browser_apikey_blocked
client-only · not sent over the network
Raw API keys must not be used from a browser context.
browser_database_url_blocked
client-only · not sent over the network
A database connection string must not be used from a browser context — it carries DB credentials.
capability_id_missing
HTTP 401 · not retryable
A capability id was expected but not provided.
capability_required
HTTP 401 · not retryable
This operation requires a capability.
datasource_registration_failed
client-only · not sent over the network
Failed to register the provided databaseUrl as a datasource.
exchange_failed
HTTP 401 · not retryable
The API-key credential exchange was rejected.
file_upload_auth_required
HTTP 401 · not retryable
File upload requires an authenticated session.
identity_missing_organization
HTTP 401 · not retryable
Authentication succeeded but resolved to no organization context.
identity_resolve_failed
HTTP 401 · not retryable
Identity resolution was rejected.
jwt_audience_mismatch
HTTP 401 · not retryable
The bearer JWT’s aud (audience) claim does not match the audience this issuer is registered with.
jwt_expired
HTTP 401 · not retryable
The bearer JWT has expired; obtain a fresh token.
jwt_invalid
HTTP 401 · not retryable
The bearer JWT could not be validated (unclassified).
jwt_issuer_untrusted
HTTP 401 · not retryable
The bearer JWT’s iss is not a registered trusted issuer. Register it via POST /v1/trusted-issuers, or check the token’s issuer claim.
HTTP 401 · not retryable
The bearer JWT is not a well-formed JWT and could not be decoded.
jwt_missing_issuer
HTTP 401 · not retryable
The bearer JWT has no iss (issuer) claim, so it cannot be routed to a trusted issuer.
jwt_missing_organization
HTTP 401 · not retryable
The bearer JWT carries no organization context — neither a fixed org for the issuer nor the configured organization claim.
jwt_missing_subject
HTTP 401 · not retryable
The bearer JWT has no sub (subject) claim to identify the user.
jwt_org_membership_denied
HTTP 403 · not retryable
The bearer JWT’s subject is not an active member of the organization in its org_id claim (removed, suspended, or the claim does not match a membership).
jwt_signature_invalid
HTTP 401 · not retryable
The bearer JWT’s signature could not be verified against the issuer’s JWKS (wrong key, rotated key, or forged token).
session_expired
HTTP 401 · not retryable
The session is invalid or expired; re-authenticate.
source_api_key_unresolved
HTTP 401 · not retryable
The source API key could not be resolved.
Permission
Credentials were valid but the action is forbidden for this caller.
byo_host_not_allowed
HTTP 403 · not retryable
The direct Postgres connector host resolves to a private, loopback, or link-local address and cannot be used.
byo_role_cannot_enforce_rls
HTTP 403 · not retryable
The direct Postgres connector role cannot enforce row-level security.
byo_role_unreadable
HTTP 403 · not retryable
The direct Postgres connector role could not be introspected.
byo_tenant_tables_unforced_rls
HTTP 403 · not retryable
Tenant tables do not have RLS forced under the direct Postgres connector role.
database_host_not_allowed
HTTP 403 · not retryable
The connected database host resolves to a private, loopback, or link-local address and cannot be used.
database_role_cannot_enforce_rls
HTTP 403 · not retryable
The connected database role cannot enforce row-level security (superuser or BYPASSRLS).
database_role_unreadable
HTTP 403 · not retryable
The connected database role could not be introspected.
database_tables_unforced_rls
HTTP 403 · not retryable
Synced tables in the connected database do not have FORCE ROW LEVEL SECURITY applied.
forbidden
HTTP 403 · not retryable
The caller lacks permission for this operation.
issuer_register_forbidden
HTTP 403 · not retryable
Registering a trusted issuer requires a secret (sk_) API key.
organization_mismatch
HTTP 403 · not retryable
The request targeted an organization the caller is not scoped to.
parent_turn_foreign_agent
HTTP 403 · not retryable
The parent turn belongs to a different agent.
test_database_not_registered
HTTP 403 · not retryable
Test mode requires a registered dev database for this org — run npx ablo init, or construct the client with databaseUrl using your test key.
turn_foreign_agent
HTTP 403 · not retryable
The turn belongs to a different agent.
wide_scope_forbidden
HTTP 403 · not retryable
A wide scope is not permitted for this caller.
Capability
The connection’s resolved scope does not cover the attempted action.
capability_invalid
HTTP 403 · not retryable
The capability is unknown, revoked, or expired.
capability_scope_denied
HTTP 403 · not retryable
The connection’s resolved scope does not cover the attempted action.
Claim & intent contention
The target is held by another participant. Usually retryable once the holder releases.
claim_conflict
HTTP 409 · not retryable
The target entity is claimed by another participant.
claim_lost
HTTP 409 · not retryable
A previously held claim was lost before the write applied.
entity_claimed
HTTP 409 · not retryable
The target entity is currently claimed; write was blocked.
intent_conflict
HTTP 409 · not retryable
An intent on the target conflicts with an active intent (server-internal alias of claim_conflict).
HTTP 400 · not retryable
The claim payload was malformed.
client-only · not sent over the network
Claiming was requested on a model that has no claim configuration.
model_claimed
HTTP 409 · not retryable
The model instance is claimed by another participant.
model_claimed_timeout
HTTP 409 · not retryable
Timed out waiting for a model claim to clear.
Conflict
The write collided with concurrent state (stale read, idempotency mismatch, incompatible change).
foreign_key_violation
HTTP 409 · not retryable
A referenced entity does not exist, or is still referenced (database foreign-key constraint).
idempotency_conflict
HTTP 409 · not retryable
The same Idempotency-Key was reused with a different request body.
incompatible_change
HTTP 409 · not retryable
The schema change is incompatible with the current schema.
stale_context
HTTP 409 · retryable
The write carried a readAt watermark that is now stale; re-read and retry.
unique_violation
HTTP 409 · not retryable
A value violates a uniqueness constraint.
Validation
The request payload or parameters were invalid. Fix the input and retry.
agent_perception_missing_context
HTTP 422 · not retryable
The agent perception request lacked required context.
capability_id_required
HTTP 400 · not retryable
A capability id is required for this request.
check_violation
HTTP 400 · not retryable
A value violates a database check constraint.
cli_invalid_arguments
client-only · not sent over the network
The CLI was invoked with an unknown flag or a malformed flag value.
commit_operation_action_required
HTTP 400 · not retryable
A commit operation is missing its action.
commit_operation_model_required
HTTP 400 · not retryable
A commit operation is missing its model.
commit_operation_required
HTTP 400 · not retryable
A commit must carry operation or operations.
commit_operation_unsupported
HTTP 400 · not retryable
A commit operation used an unsupported action.
commit_operations_ambiguous
HTTP 400 · not retryable
A commit supplied both operation and operations.
commit_too_many_operations
HTTP 400 · not retryable
A commit exceeded the per-commit operation limit; split it into smaller batches.
constraint_violation
HTTP 400 · not retryable
A database integrity constraint was violated.
datasource_connection_unsupported
HTTP 400 · not retryable
This deployment cannot register a direct (connection string) datasource — use the signed endpoint kind.
duration_invalid
client-only · not sent over the network
A duration value was not a number of seconds or a “500ms” | ”30s” | “3m” | “24h” string.
events_required
HTTP 400 · not retryable
The request must include a non-empty events array.
idempotency_key_too_long
HTTP 400 · not retryable
The supplied Idempotency-Key exceeds the maximum length.
ingest_failed
HTTP 400 · not retryable
The source-event ingest failed.
intent_id_required
HTTP 400 · not retryable
An intent id is required for this request.
invalid_body
HTTP 400 · not retryable
The request body was missing, unparseable, or the wrong shape.
invalid_id
HTTP 400 · not retryable
The request carried an invalid id.
invalid_intent
HTTP 400 · not retryable
The intent request was invalid.
invalid_json
HTTP 400 · not retryable
The request body was not valid JSON.
invalid_model
HTTP 400 · not retryable
The request named an invalid model.
invalid_participant_kind
HTTP 400 · not retryable
The participant kind is invalid.
invalid_request
HTTP 400 · not retryable
The request parameters were invalid.
invalid_schema
HTTP 400 · not retryable
The submitted schema could not be parsed.
mesh_message_from_id_spoof
HTTP 403 · not retryable
The mesh message from id does not match the authenticated sender.
mesh_message_from_kind_mismatch
HTTP 403 · not retryable
The mesh message from kind does not match the sender.
HTTP 400 · not retryable
The mesh message failed input validation.
model_identifier_missing
HTTP 400 · not retryable
The model payload is missing its identifier.
model_query_failed
HTTP 400 · not retryable
The model query failed.
model_required_field_missing
HTTP 400 · not retryable
A required field was absent from the model payload.
narrow_scope_required
HTTP 400 · not retryable
A narrowed scope is required for this request.
not_null_violation
HTTP 400 · not retryable
A required field was missing (database not-null constraint).
org_id_required
HTTP 400 · not retryable
An organization id is required for this request.
presence_identity_required
HTTP 400 · not retryable
Both userId and organizationId are required.
queries_required
HTTP 400 · not retryable
The request must include a non-empty queries array.
query_invalid_identifier
HTTP 400 · not retryable
The query contained an invalid identifier.
query_unknown_relation
HTTP 400 · not retryable
The query referenced an unknown relation.
query_unsupported_operator
HTTP 400 · not retryable
The query used an unsupported operator.
schema_definition_invalid
client-only · not sent over the network
A schema definition value was invalid (bad column identifier, non-finite backfill, or unsupported schema-JSON version).
schema_too_large
HTTP 413 · not retryable
The submitted schema exceeds the maximum size.
snapshot_reserved_key
HTTP 400 · not retryable
A snapshot used a reserved key name.
client-only · not sent over the network
The data-source ORM adapter could not map a schema model onto the backing client (missing delegate or model).
source_event_invalid
client-only · not sent over the network
A data-source outbox event could not be built — the operation carries no entity id and none was supplied.
source_operation_id_required
client-only · not sent over the network
A data-source operation arrived without the entity id it targets.
task_id_required
HTTP 400 · not retryable
A task id is required for this request.
turn_validation_failed
HTTP 422 · not retryable
The agent turn failed server-side validation.
upload_fields_required
HTTP 400 · not retryable
A required upload field was missing.
upload_items_required
HTTP 400 · not retryable
The request must include a non-empty items array.
usage_invalid
HTTP 400 · not retryable
The usage request was invalid.
write_options_invalid
client-only · not sent over the network
The write options (idempotencyKey / label / wait / readAt / onStale / intent) failed validation against the write-options schema.
Not found
The referenced resource does not exist (or is hidden by scope).
capability_not_found
HTTP 404 · not retryable
No capability exists with the given id.
entity_not_found
HTTP 404 · not retryable
The referenced entity does not exist.
model_not_found
HTTP 404 · not retryable
The referenced model row does not exist.
mutate_update_entity_not_found
HTTP 404 · not retryable
The entity targeted by an update does not exist.
parent_turn_not_found
HTTP 404 · not retryable
The referenced parent turn does not exist.
turn_not_found
HTTP 404 · not retryable
The referenced turn does not exist.
Tenant / schema resolution
The named model could not be resolved in the tenant schema.
model_not_tenant_scoped
HTTP 400 · not retryable
The model is not tenant-scoped and cannot be queried this way.
mutate_create_unknown_model
HTTP 400 · not retryable
Created a model the server does not know. Run ablo push (or keep ablo dev running) to upload ablo/schema.ts first — the server keeps its own copy of the schema.
server_execute_unknown_model
HTTP 400 · not retryable
Wrote to a model the server does not know. The server keeps its own copy of the schema — run ablo push (or keep ablo dev running) to upload ablo/schema.ts before writing to new or changed models.
tenant_model_columns_unknown
HTTP 400 · not retryable
The tenant model’s columns could not be resolved.
tenant_model_missing_organization_id
HTTP 400 · not retryable
The tenant model is missing the organization_id column required for isolation.
unknown_model
HTTP 400 · not retryable
Named a model the server does not know. Run ablo push (or keep ablo dev running) to upload ablo/schema.ts — the server keeps its own copy of the schema.
Schema
Schema declaration or migration problems.
drop_field
client-only · not sent over the network
Migration would drop a field (destructive classification).
drop_model
client-only · not sent over the network
Migration would drop a model (destructive classification).
enum_value_removed
client-only · not sent over the network
Migration removes an enum value (destructive classification).
lossy_recreate
client-only · not sent over the network
Migration would require a lossy table recreate.
made_required
client-only · not sent over the network
Migration would make an existing field required.
query_relation_target_unknown
HTTP 500 · not retryable
A relation targets a model the schema does not define.
required_field_added
client-only · not sent over the network
Migration adds a new required field.
risky_cast
client-only · not sent over the network
Migration would perform a risky column type cast.
schema_field_consecutive_caps
HTTP 400 · not retryable
A schema field name has consecutive capital letters.
schema_field_not_camelcase
HTTP 400 · not retryable
A schema field name is not camelCase.
schema_grants_identifier_unsafe
HTTP 400 · not retryable
A grants declaration referenced an unsafe identifier.
schema_grants_relation_kind
HTTP 400 · not retryable
A grants relation referenced an invalid kind.
schema_grants_relation_missing
HTTP 400 · not retryable
A grants declaration referenced a missing relation.
schema_grants_shape_invalid
HTTP 400 · not retryable
A grants declaration has an invalid shape.
schema_grants_target_not_scope_root
HTTP 400 · not retryable
A grants target is not a scope root.
HTTP 400 · not retryable
A mutable schema is missing its required meta block.
schema_scope_invalid
HTTP 500 · not retryable
The model’s scope predicate could not be built.
schema_scope_kind_invalid
HTTP 400 · not retryable
A scope kind in the schema is invalid.
schema_table_invalid
HTTP 500 · not retryable
The model’s table identifier is invalid.
Intent lease
Intent-lease acquisition, queueing, and coordination.
grant_timeout
HTTP 504 · retryable
Timed out waiting for a capability grant.
intent_lease_unavailable
HTTP 503 · retryable
The intent-lease coordination subsystem is unavailable; retry.
intent_not_wired
client-only · not sent over the network
Intent support was used but is not wired in this runtime.
intent_queued
HTTP 409 · retryable
The intent was queued behind an active lease holder.
intent_wait_aborted
HTTP 409 · retryable
Waiting for the intent lease was aborted.
intent_wait_poll_interval_required
client-only · not sent over the network
A poll interval is required when waiting on an intent.
slide_intent_missing_deck_id
HTTP 400 · not retryable
A slide intent was missing its deck id.
slide_intent_unknown_sibling
HTTP 400 · not retryable
A slide intent referenced an unknown sibling slide.
Bootstrap
Initial snapshot fetch problems.
bootstrap_fetch_timeout
HTTP 504 · retryable
The bootstrap fetch timed out.
bootstrap_offline
HTTP 503 · retryable
Bootstrap could not run because the client is offline.
bootstrap_offline_no_cache
HTTP 503 · not retryable
Bootstrap is offline and no cached snapshot is available.
bootstrap_response_invalid
HTTP 502 · retryable
The bootstrap response was malformed.
bootstrap_response_schema_invalid
HTTP 502 · retryable
The bootstrap response failed schema validation.
Transport
Network, connection, queue, and timeout failures. Generally retryable.
base_url_missing
client-only · not sent over the network
No base URL was configured for the client.
commit_failed
HTTP 500 · retryable
The commit failed to apply.
commit_no_result
HTTP 504 · retryable
The commit was sent but no result frame arrived.
commit_offline_grace_expired
HTTP 503 · not retryable
The offline grace window expired before the commit could be sent.
HTTP 502 · retryable
The credential exchange returned a malformed response.
exchange_network_error
HTTP 503 · retryable
A network error occurred during credential exchange.
fetch_unavailable
client-only · not sent over the network
No fetch implementation is available in this environment.
flush_timeout
HTTP 504 · retryable
Timed out flushing the transaction queue.
identity_network_error
HTTP 503 · retryable
A network error occurred resolving identity.
instance_at_capacity
HTTP 503 · retryable
The server is at connection capacity. Retry shortly — transient and not specific to your credentials.
queue_too_deep
HTTP 503 · retryable
The transaction queue exceeded its depth limit.
source_network_error
HTTP 503 · retryable
A network error occurred talking to the source.
sync_not_ready
client-only · not sent over the network
A sync operation was attempted before the client was ready.
wait_for_timeout
HTTP 504 · retryable
A wait-for condition timed out.
ws_not_ready
client-only · not sent over the network
A frame was sent before the WebSocket was connected.
Rate limit
Too many requests. Back off before retrying.
connection_limit_exceeded
HTTP 429 · retryable
Too many concurrent WebSocket connections for this principal or organization. Close idle connections, or retry once others drain.
quota_exceeded
HTTP 429 · retryable
The organization exceeded its configured usage quota.
Server
Server-side failures. Generally retryable with backoff.
capability_auth_disabled
HTTP 503 · not retryable
Capability authentication is disabled on this server.
entity_fetch_failed
HTTP 500 · retryable
The entity fetch failed.
internal_error
HTTP 500 · retryable
An unexpected server error occurred.
migration_failed
HTTP 500 · not retryable
The schema migration failed to apply.
presigned_url_failed
HTTP 500 · retryable
Failed to generate a presigned upload URL.
provisioner_unavailable
HTTP 503 · not retryable
No database provisioner is configured.
quota_lookup_failed
HTTP 503 · retryable
The quota decision could not be loaded.
task_id_missing
HTTP 502 · retryable
The task-create response did not include an id.
tenant_routing_failed
HTTP 500 · retryable
The org’s registered database could not be resolved or dialed. Ablo never falls back to shared storage for a dedicated tenant — retry, and check the datasource status if it persists.
turn_close_failed
HTTP 500 · retryable
The agent turn failed to close cleanly.
turn_open_failed
HTTP 500 · retryable
The agent turn failed to open.
Client (SDK) invariants
Local SDK usage errors — never sent over the network. No HTTP status.
db_not_opened
client-only · not sent over the network
The local database was accessed before it was opened.
db_store_not_found
client-only · not sent over the network
The requested IndexedDB object store does not exist.
db_unknown_action_type
client-only · not sent over the network
An unknown database action type was dispatched.
idb_unavailable
client-only · not sent over the network
IndexedDB is unavailable in this environment.
invalid_options
client-only · not sent over the network
The Ablo client was constructed with invalid or incomplete options.
lazy_ref_db_missing
client-only · not sent over the network
A lazy reference was resolved without a database handle.
lazy_ref_pool_missing
client-only · not sent over the network
A lazy reference was resolved without a model pool.
client-only · not sent over the network
The meta database was accessed before initialization.
mock_mutation_failed
client-only · not sent over the network
A mock mutation adapter was configured to fail.
mock_unsupported_operation
client-only · not sent over the network
A mock adapter received an unsupported operation.
model_class_not_registered
client-only · not sent over the network
The model class is not registered with the store.
model_disposed
client-only · not sent over the network
The model instance has been disposed.
model_not_registered
client-only · not sent over the network
The model is not registered with the store.
mutator_registry_duplicate
client-only · not sent over the network
Two mutator definitions registered under the same name.
mutator_registry_unnamed_def
client-only · not sent over the network
A mutator definition was registered without a name.
mutators_schema_missing
client-only · not sent over the network
Mutators were registered without a schema.
no_ablo_provider
client-only · not sent over the network
An Ablo hook was used outside of an Ablo provider.
no_sync_group_provider
client-only · not sent over the network
A sync-group hook was used outside of its provider.
pool_model_class_not_registered
client-only · not sent over the network
The model class is not registered with the pool.
pool_registry_missing
client-only · not sent over the network
The model pool registry is not initialized.
pool_subscribe_unregistered
client-only · not sent over the network
Subscribed to a model that is not registered with the pool.
query_returns_unknown_model
client-only · not sent over the network
A query returned a model the registry does not know.
registry_invalid_constructor
client-only · not sent over the network
A model was registered with an invalid constructor.
registry_not_initialized
client-only · not sent over the network
The registry was used before initialization.
registry_property_conflict
client-only · not sent over the network
Two registered models declared a conflicting property.
registry_reference_unknown_target
client-only · not sent over the network
A relation referenced an unknown target model.
registry_reference_unresolved
client-only · not sent over the network
A relation reference could not be resolved.
registry_unknown_model
client-only · not sent over the network
The registry has no entry for the requested model.
store_create_schema_missing
client-only · not sent over the network
Store.create was called without a schema.
store_manager_unknown_model
client-only · not sent over the network
The store manager has no entry for the requested model.
store_query_schema_missing
client-only · not sent over the network
Store.query was called without a schema.
store_query_unknown_model
client-only · not sent over the network
Store.query named a model the store does not know.
sync_client_db_missing
client-only · not sent over the network
The sync client has no database handle.
sync_context_missing_provider
client-only · not sent over the network
Sync context was read outside of its provider.
transaction_mutate_unknown_model
client-only · not sent over the network
A transaction mutated a model the registry does not know.
transaction_read_unknown_model
client-only · not sent over the network
A transaction read a model the registry does not know.
undo_entry_invalid
client-only · not sent over the network
An undo entry failed inverse-op schema validation.
undo_scope_schema_missing
client-only · not sent over the network
An undo scope was opened without a schema.