General
Error Codes
Every error group and code the Rivet HTTP API and connection protocol can return.
Errors are identified by group and code. See Errors for the response format and Connect for how they arrive over a WebSocket connection.
The Status column shows the HTTP status the error is returned with. When the gateway and the control plane disagree, both are listed. Codes without a status use the default for where they were raised: 400 from the control plane and gateway, and 500 from inside the actor runtime, where the message is also replaced with a generic internal error unless the code is listed here with a status. Errors thrown by your own actor code with UserError use the user group with whatever code you supply, and always return 400.
Messages may contain placeholders in braces that are filled in at runtime. Match on group and code, not on message.
actor api auth config connection datacenter depot depot_kv engine envoy group guard inspector kv message namespace napi pool protocol queue registry request runner runner_pool schedule serverless_runner_pool services sqlite state_machine topology ups user validation wasm ws
actor
Actor lifecycle, addressing, and actions.
| Code | Status | Message |
actor.aborted | 400 | Actor aborted |
actor.action_timed_out | 408 | Action timed out |
actor.create_pending | 409 | Actor creation may still be in progress; do not retry creation automatically. |
actor.destroyed | | Actor was destroyed. |
actor.destroying | | Actor is destroying. |
actor.dropped_reply | | Actor reply channel was dropped without a response. |
actor.duplicate_key | | Actor key already in use. |
actor.fork_failed | | The actor fork failed. |
actor.fork_pending | | The actor fork is still in progress; read the new actor later. |
actor.fork_too_deep | | The actor is too many forks deep to fork again. |
actor.fork_unavailable | | Actor forks are unavailable until the engine upgrade finishes; retry. |
actor.input_too_large | | Actor input too large. |
actor.invalid_cursor | | The actor listing cursor is malformed. |
actor.invalid_include_destroyed | | The actor listing include_destroyed flag must be true or false. |
actor.invalid_input | | The input is not valid base64. |
actor.invalid_key | | Actor key is invalid. |
actor.invalid_key_encoding | | Actor key is not in the canonical slash-separated form produced by serializeActorKey. |
actor.invalid_limit | | The actor listing limit must be an integer from 1 to 100. |
actor.invalid_listing | | Listing actors requires a name or actor IDs. |
actor.invalid_name | | Actor name is invalid. |
actor.invalid_operation | | Actor operation is invalid. |
actor.invalid_request | | Invalid hibernatable websocket connection ID |
actor.invalid_version | | The requested actor version cannot be created here. |
actor.js_callback_unavailable | | JavaScript callback unavailable |
actor.key_owned_elsewhere | | The actor key is owned by another datacenter. |
actor.key_too_large | | Key label too large. |
actor.kv_key_too_large | | A KV key is too large. |
actor.kv_response_too_large | | The KV response is too large. Read fewer keys per request. |
actor.kv_too_many_keys | | The KV request names too many keys. |
actor.legacy_moved_away | | The actor event reached an abandoned copy of an actor being moved by an engine upgrade. Clients never receive this code: the engine delivers the event to the original actor. |
actor.method_not_allowed | 405 | Method not allowed |
actor.migrate_from_v2_unsupported | | The cluster cannot hold actors for a V2 migration yet. |
actor.migrating_from_v2 | | The actor is moving to this cluster from V2. Retry after the hinted delay. |
actor.missing_input | | Actor input is missing. |
actor.moving | | The actor is being moved by an engine upgrade. Clients never receive this code: the gateway retries the request, then answers guard.service_unavailable with reason actor_moving and a Retry-After hint. |
actor.not_configured | | Actor capability is not configured. |
actor.not_found | 404 | The actor does not exist or was destroyed. |
actor.not_ready | | Actor is not ready. |
actor.not_registered | | Actor factory is not registered. |
actor.overloaded | | Actor is overloaded. |
actor.panicked | | Actor task panicked. |
actor.shutdown_timeout | | Actor shutdown timed out. |
actor.starting | | Actor is starting. |
actor.stopping | | Actor is stopping. |
api
Malformed requests to the control plane.
| Code | Status | Message |
api.forbidden | 403 | Access denied |
api.internal_error | | An internal server error occurred |
api.not_found | 404 | The requested resource was not found |
api.unauthorized | 401 | Authentication required |
auth
Token validation and permissions.
| Code | Status | Message |
auth.insufficient_permissions | 403 | Insufficient permissions to access this resource. |
auth.invalid_token | 401 | Authentication token is invalid. |
auth.issuance_disabled | 503 | JWT issuance is not enabled for this deployment. |
auth.issuance_unavailable | 503 | The server could not issue an authentication token because the signing service is temporarily unavailable. Retry the request. |
auth.operation_unavailable | | The operation cannot be granted until every engine worker supports it. Retry after the engine upgrade finishes. |
auth.token_expired | 401 | Authentication token has expired. |
auth.verification_unavailable | 503 | The server could not verify the authentication token because verification keys are temporarily unavailable. Retry the request. |
config
| Code | Status | Message |
config.endpoint_mismatch | | Endpoint mismatch. |
config.namespace_mismatch | | Namespace mismatch. |
connection
Actor connections opened through the connection protocol.
| Code | Status | Message |
connection.disconnect_failed | | Connection disconnect failed |
connection.not_configured | | Connection callback is not configured |
connection.not_found | | Connection was not found |
connection.not_hibernatable | | Connection is not hibernatable |
connection.restore_not_found | | Hibernatable connection restore target was not found |
datacenter
| Code | Status | Message |
datacenter.not_found | | The provided datacenter does not exist. |
depot
| Code | Status | Message |
depot.command_too_large | | The command exceeds the byte limit. |
depot.conflict | | The command conflicted with a concurrent change to the volume. |
depot.corrupt | | The volume's stored data failed a consistency check. |
depot.database_not_found | | Database was not found in this bucket branch. |
depot.fenced | | A newer owner holds the volume; the command was not applied by this owner. |
depot.head_fence_mismatch | | SQLite head fence mismatch. |
depot.legacy_layout | | The actor volume predates the /actor layout and must be reinitialized. |
depot.overloaded | | The storage host refused the command; retry after the hinted delay. |
depot.quota_exceeded | | Not enough space left in Depot. |
depot.read_interrupted | | The storage read was interrupted; retry after the hinted delay. |
depot.request_deadline_exceeded | | The command deadline elapsed; its outcome may be unknown. |
depot.response_version_unavailable | | The command's answer cannot be expressed at the version its caller reads; it may have been applied. |
depot.routing_unavailable | | No tablet maintainer route is available. |
depot.scope_revoked | | The caller scope ended; submitted work may still complete. |
depot.storage_unavailable | | Depot storage is not available in this build. |
depot.unavailable | | The storage host could not finish the command; its outcome may be unknown. |
depot.unknown_command | | The maintainer does not recognize this command. |
depot.volume_deleted | | The KV database volume was deleted. |
depot.volume_not_found | | The KV database volume does not exist. |
depot_kv
| Code | Status | Message |
depot_kv.closed | | The engine is closed. |
depot_kv.conflict | | The transaction conflicts with a later write. |
depot_kv.corrupt | | Stored data failed its integrity checks. |
depot_kv.failed | | The write failed. |
depot_kv.invalid_key | | The key or range is invalid. |
depot_kv.overloaded | | The engine commit queue is full. |
depot_kv.storage | | A block device read failed. |
depot_kv.too_large | | The transaction exceeds a configured limit. |
depot_kv.too_old | | The snapshot is too old. |
engine
| Code | Status | Message |
engine.binary_not_found | | Engine binary was not found. |
engine.binary_unavailable | | Engine binary is unavailable. |
engine.checksum_mismatch | | Engine binary checksum mismatch. |
engine.download_failed | | Engine binary download failed. |
engine.health_check_failed | | Engine health check failed. |
engine.incompatible_binary | | The Engine binary is incompatible with this RivetKit. |
engine.incompatible_engine | | An incompatible engine is already running on the endpoint. |
engine.invalid_endpoint | | Engine endpoint is invalid. |
engine.missing_pid | | Engine process is missing a pid. |
engine.not_ready | | Engine did not become ready. |
engine.port_occupied | | Engine port is occupied by a different runtime. |
engine.spawn_endpoint_conflict | | Engine spawn conflicts with the configured endpoint |
envoy
| Code | Status | Message |
envoy.connect_overloaded | | Too many runners are connecting at once. Retry after the hint. |
envoy.connect_unavailable | | Storage could not register the runner yet. Retry after the hint. |
envoy.invalid_namespace_name | | Namespace name is invalid. |
envoy.invalid_pool_name | | Pool name is invalid. |
envoy.malformed_message | | The message could not be decoded. |
group
| Code | Status | Message |
group.archived | | The group is archived and closed for good. |
group.exists | | A different group already exists with this id. |
group.has_children | | The group has a child that is not archived. |
group.lineage_too_deep | | The group's lineage has reached the depth cap. |
group.not_found | | The group does not exist. |
guard
The gateway that routes requests to actors, including request parsing, rate limits, and timeouts.
| Code | Status | Message |
guard.actor_ready_timeout | 503 | Timed out waiting for actor to become ready. Ensure that the pool selector is accurate and there are runners available in the namespace you created this actor. |
guard.actor_stopped_while_waiting | 503 | Actor stopped while waiting for a response. |
guard.invalid_request | | Invalid request. |
guard.missing_header | | Missing header required for routing. |
guard.query_invalid_params | | invalid query gateway params |
guard.rate_limit | 429 | Too many requests. Try again later. |
guard.request_timeout | 504 | Timed out waiting for the actor to become ready. |
guard.service_unavailable | 503 | Service unavailable. |
inspector
| Code | Status | Message |
inspector.invalid_request | | Invalid inspector request |
inspector.unauthorized | | Inspector request requires a valid bearer token |
kv
Low-level KV storage inside an actor.
| Code | Status | Message |
kv.key_too_large | 400 | KV key is too large. |
kv.value_too_large | 400 | KV value is too large. |
message
Message size limits on connections.
| Code | Status | Message |
message.incoming_too_long | 400 | Incoming message too long. |
message.outgoing_too_long | 400 | Outgoing message too long |
namespace
Namespace lookup and creation.
| Code | Status | Message |
namespace.archived | | The namespace is archived or being archived. |
namespace.backfill_pending | | The namespace's volumes from before volume groups are still being moved into its group; retry later. |
namespace.backfill_skipped | | The namespace still has actors from before volume groups that its backfill could not move; destroy them first. |
namespace.creating | 503 | The namespace is still being created; retry. |
namespace.failed | | The namespace's fork was refused and its name is retired. |
namespace.has_forks | | A fork of this namespace is not archived; archive it first. |
namespace.has_nodes | | A node of this namespace is connected; stop its nodes before archiving it. |
namespace.invalid | | Namespace list limit must be between 1 and 100. |
namespace.lineage_too_deep | | The namespace is as many forks below its root as the lineage depth cap allows. |
namespace.migrating_from_v2 | | The namespace cannot be forked while a V2 migration moves actors into it. |
namespace.name_not_unique | | A namespace with this name already exists. |
namespace.not_forkable | | The namespace cannot be forked until its volumes from before volume groups are moved into its group. |
namespace.not_found | | The namespace does not exist. |
namespace.pending | | The namespace's creation or fork has not finished; retry. |
namespace.protected | | The default namespace cannot be archived. |
napi
| Code | Status | Message |
napi.invalid_argument | | Invalid native argument |
napi.invalid_state | | Invalid native state |
pool
| Code | Status | Message |
pool.invalid | | Node pool configuration is invalid. |
pool.nodes_connected | | The node pool still has connected nodes. |
pool.not_found | | The node pool does not exist. |
pool.serverless_unsupported | | Serverless node pools are not supported. |
protocol
Encoding and framing of connection protocol messages.
| Code | Status | Message |
protocol.invalid_actor_connect_request | | Invalid actor-connect request. |
protocol.invalid_http_request | | Invalid HTTP request. |
protocol.invalid_http_response | | Invalid HTTP response. |
protocol.invalid_persisted_data | | Invalid persisted actor data. |
protocol.unsupported_encoding | | Unsupported protocol encoding. |
queue
Actor queues.
| Code | Status | Message |
queue.already_completed | 400 | Queue message was already completed |
queue.complete_not_configured | 400 | Queue message does not support completion |
queue.completion_waiter_conflict | 400 | Queue completion waiter conflict |
queue.completion_waiter_dropped | 400 | Queue completion waiter dropped before response |
queue.full | 400 | Queue is full |
queue.invalid_message_key | 400 | Queue message key is invalid |
queue.message_identity_mismatch | 400 | Queue message identity does not match |
queue.message_too_large | 400 | Queue message is too large |
queue.timed_out | 400 | Queue wait timed out |
registry
| Code | Status | Message |
registry.envoy_start_failed | | Envoy failed to connect to the engine. |
registry.shut_down | | Registry is shut down. |
request
| Code | Status | Message |
request.invalid | | Invalid request. |
runner
| Code | Status | Message |
runner.not_found | | The runner does not exist. |
runner_pool
| Code | Status | Message |
runner_pool.invalid | | Invalid runner pool. |
runner_pool.not_found | | No config for this runner exists. |
schedule
| Code | Status | Message |
schedule.interrupted | 400 | Scheduled action was interrupted. |
schedule.invalid_cron_expression | 400 | Cron expression is invalid. |
schedule.invalid_interval | 400 | Schedule interval is invalid. |
schedule.invalid_max_history | 400 | Schedule history limit is invalid. |
schedule.invalid_name | 400 | Schedule name is invalid. |
schedule.invalid_schedule_row | 400 | Stored schedule data is invalid. |
schedule.invalid_timezone | 400 | Schedule timezone is invalid. |
schedule.max_schedules_exceeded | 400 | Actor schedule limit reached. |
serverless_runner_pool
| Code | Status | Message |
serverless_runner_pool.not_found | | No serverless pool for this runner exists. |
services
| Code | Status | Message |
services.binary_not_found | | Services binary was not found. |
services.binary_unavailable | | Services binary is unavailable. |
services.metadata_failed | | Services compatibility could not be verified. |
services.protocol_mismatch | | Services is newer than the local Engine protocol. |
services.readiness_failed | | Services did not become ready. |
services.start_failed | | Services failed to start. |
sqlite
| Code | Status | Message |
sqlite.closed | | SQLite database is closed. |
sqlite.invalid_bind_parameter | | Invalid SQLite bind parameter. |
sqlite.invalid_compile_options | | SQLite requires SQLITE_ENABLE_BATCH_ATOMIC_WRITE and SQLITE_DIRECT_OVERFLOW_READ=0. Rebuild with LIBSQLITE3_FLAGS="SQLITE_ENABLE_BATCH_ATOMIC_WRITE SQLITE_DIRECT_OVERFLOW_READ=0". |
sqlite.manual_transaction_open | | SQLite manual transaction stayed open. |
sqlite.not_configured | | SQLite is not configured. |
sqlite.remote_execution_failed | | Remote SQLite execution failed. |
sqlite.remote_fence_mismatch | | Remote SQLite generation is stale. |
sqlite.remote_indeterminate_result | | Remote SQLite result is indeterminate. |
sqlite.remote_unavailable | | Remote SQLite is unavailable. |
sqlite.storage_overloaded | | SQLite storage is overloaded. |
sqlite.storage_timeout | | SQLite storage timed out. |
sqlite.transaction_closed | | SQLite transaction coordinator is closed. |
sqlite.transaction_connection_lost | | SQLite transaction connection was lost. |
sqlite.transaction_expired | | SQLite transaction expired. |
sqlite.transaction_invalid_argument | | Invalid SQLite transaction argument. |
sqlite.transaction_queue_full | | SQLite transaction queue is full. |
sqlite.transaction_terminal | | SQLite transaction handle is terminal. |
sqlite.transaction_too_large | | SQLite transaction is too large. |
sqlite.transaction_unknown | | Unknown SQLite transaction handle. |
sqlite.unavailable | | SQLite is unavailable. |
sqlite.writer_busy | | SQLite writer is busy. |
state_machine
| Code | Status | Message |
state_machine.machine_not_found | | The state machine does not exist. |
topology
| Code | Status | Message |
topology.unsupported_version | | The peer does not read any version of this family that this binary writes. |
topology.version_unavailable | | No version of this family is both readable by every storage worker and writable here. |
topology.version_unknown | | The storage workers that read persisted data are unknown. |
ups
| Code | Status | Message |
ups.consumer_closed | | The consumer closed without replying; the operation may have executed. |
ups.dispatch_rejected | | The caller revoked the request before dispatch. |
ups.endpoint_unresolved | | The worker's endpoint could not be resolved; the request was not sent. |
ups.invalid_message | | The message exceeds the limit or has an invalid subject. |
ups.invalid_stream | | The packet stream is malformed or ended without a terminal frame. |
ups.no_responders | | The worker has no consumer for this subject. |
ups.overloaded | | UPS capacity is full; the operation was not admitted. |
ups.subscription_exists | | This worker already has a consumer for the subject. |
ups.timeout | | The operation deadline expired; it may still have completed. |
ups.transport | | Worker transport failed; the operation may have executed. |
ups.unexpected_packet | | Expected exactly one packet followed by the end of the stream. |
ups.unknown_worker | | The worker is not in current membership. |
ups.wrong_worker | | The target worker incarnation has changed. |
user
Errors thrown by your actor code. The code is whatever you pass to UserError.
validation
Request validation.
| Code | Status | Message |
validation.invalid_input | | Invalid input. |
wasm
| Code | Status | Message |
wasm.invalid_config | | Invalid wasm configuration. |
wasm.invalid_state | | Invalid wasm state |
ws
WebSocket handling for the connection protocol and onWebSocket handlers.
| Code | Status | Message |
ws.connection_closed | | Normal connection close. |
ws.eviction | | The websocket has been evicted and should not attempt to reconnect. |
ws.invalid_request | | The websocket could not open due to an invalid request. |
ws.timed_out | | Ping timed out. |