Skip to content

Errors and cancellation

BoxDB owns the public error names in every language. Engine failures use BOXDB_* names such as BOXDB_CONSTRAINT_UNIQUE; numeric result codes currently retain the embedded engine’s primary and extended values. Messages are for people and must not be parsed to identify failures.

ClientErrorNumeric engine detailsCause lookup
Rustboxdb::Error, code()result_code() / extended_code(), returning Option<i32>std::error::Error::source()
TypeScriptBoxDBError, coderesultCode / extendedCode, optional numberscause; findBoxDBError(error) follows causes and aggregate members
Go*boxdb.Error, CodeResultCode / ExtendedCode, optional *interrors.As; errors.Is for standard errors

The Rust error type owns engine-code naming and the serialized error object used by the Go bridge. TypeScript preserves the native code and exception. A UNIQUE violation has code BOXDB_CONSTRAINT_UNIQUE, primary code 19, and extended code 2067. Numeric codes are absent when the engine did not report the failure; zero is not a placeholder for missing information. Updating a read-only column has code BOXDB_CONSTRAINT_READONLY, primary code 19, and extended code 1811.

Validation, filesystem I/O, closed connections, unusable connections after publication failure, and internal infrastructure failures have separate BOXDB_* categories. Failures raised by BoxDB SQL functions such as boxdb_apply or boxdb_changeset use BOXDB_CONSTRAINT_FUNCTION unless an engine code applies. Readable-file lock contention retains its OS cause without inventing numeric engine codes. Rust retains I/O, parser, JSON and YAML sources; with_context() retains codes and sources. Database::try_memory() provides fallible initialization and is used by both native clients.

Cancellation and cleanup

Go matches cancellation and deadlines through errors.Is(err, context.Canceled) or errors.Is(err, context.DeadlineExceeded). When a native operation is interrupted or stops waiting for a lock after the context ends, the context error and the native BoxDB error are joined. A native failure unrelated to cancellation is retained rather than replaced merely because the context has ended. Cancellation before execution has no native failure to attach.

Go transaction completion retains both the operation and cleanup errors. A failed session reset invalidates the connection and retains its original reason. The driver’s pool-reset boundary can signal driver.ErrBadConn before an operation; a transaction result does not request automatic retry after an operation may have executed. See the Go contracts for errors.Join and ErrBadConn.

TypeScript transactions use explicit handles and await using: unfinished transactions roll back during disposal. A failed commit keeps a still-active native transaction available for repair or retry. Disposal retains operation and rollback failures through JavaScript’s explicit resource management protocol. Transaction deadline expiry uses BOXDB_TRANSACTION_TIMEOUT, interrupts running SQL and rolls back before releasing root requests waiting on the connection. Expired handles retain the timeout reason for further queries and commit calls. TypeScript read-only transactions use BOXDB_READONLY for forbidden SQL writes. Their restriction is inherited by savepoints and released before waiting root work resumes; an explicitly enabled pre-existing query_only setting is preserved. Argument errors use TypeError or RangeError; both unsafe integer numbers and bigint outside the combined INT64/UINT64 range (-2^63 through 2^64 - 1) use RangeError.

Signals reject cancelled TypeScript requests with the caller’s reason. Rollback and connection-close cleanup are not cancelled by the same signal. SQL runs on a dedicated native worker, including busy waits. See the client guide for the transaction ownership and close contracts.

TypeScript integers and integrations

Integer storage values always return as bigint; REAL values return as number. lastInsertRowid and write counts also use bigint. There is no precision mode switch. Safe integer numbers and booleans bind as integers. Applications must explicitly convert bigint when serializing JSON. Tagged-query result methods reuse the same native execution and rejected error.

Drizzle may return BoxDBError directly or put it in an ORM error’s cause, depending on the API used. findBoxDBError() handles both, as well as aggregates, and avoids cycles. Use bigint schema types for integer values and the adapter’s migrate() helper for an INTEGER migration journal and bigint result metadata.

Better Auth maps booleans and numeric fields to its expected application types. db0 preserves bigint values and write metadata. All adapters borrow the client.

See the TypeScript and Go guides for usage. Contract coverage lives in the Rust tests, Go tests, and TypeScript tests. The CLI reports errors on stderr with exit status 1. --json emits structured errors; maintenance reports are written separately to stdout.

Operation state and unusable connections

Core connection errors retain the operation, outcome, transaction state and connection usability when known. Rust exposes operation(), outcome(), in_transaction(), connection_usable() and cleanup_errors(). TypeScript uses operation, outcome, inTransaction, connectionUsable and cleanupErrors; Go uses Operation, Outcome, InTransaction, ConnectionUsable and Cleanup. Missing state remains absent rather than being guessed.

Read/preparation failures report not_applied. Failed writes conservatively report unknown, so callers must not blindly retry them. A failed SQL script can have committed earlier statements; its outcome is unknown even if its final statement was a read. Native cleanup failures remain attached to the primary error. No write replay is requested by the driver after an operation fails.

BOXDB_CORRUPT and BOXDB_NOTADB invalidate the normal connection. Further queries and preparation return BOXDB_UNAVAILABLE; Go also marks that connection invalid for the pool. Constraint and argument errors do not invalidate it. BOXDB_METADATA, BOXDB_UNSUPPORTED_CODEC and BOXDB_FORMAT distinguish schema metadata, codec-version and file-format problems from engine corruption. Invalid projected logical values use BOXDB_INVALID_VALUE, keeping stored-data failures distinct from invalid query arguments.

Readable publication failures invalidate the connection. A failure before file replacement reports not_applied; a failure after replacement, such as directory synchronization failure, reports unknown. Reopen and inspect durable data before deciding whether to repeat an operation. See file diagnostics.