Errors
ValtheraDB uses a unified, structured error model. Errors raised by the core and by adapters during database operations are instances of ValtheraError, carrying a machine-readable code and optionally a suggestion and a context object. Errors thrown by your own code, such as a db.transaction() callback or a plugin, are not wrapped and may be plain Error instances.
import { isValtheraError } from "@wxn0brp/db-core/errors";
try {
await db.users.add({ name: "Alice" });
} catch (err) {
if (isValtheraError(err)) {
console.log(err.name); // "ValtheraError" or a subclass name
console.log(err.code); // e.g. "QUERY_INVALID"
console.log(err.message);
console.log(err.suggestion); // optional hint
console.log(err.context); // e.g. { op: "add", collection: "users", adapter: "1.2.3" }
}
}
Error Codes
| Code | Meaning |
|---|---|
UNSUPPORTED_OPERATION |
The operation is not supported by the adapter or backend |
ADAPTER_ERROR |
Generic adapter/driver failure |
ADAPTER_INIT |
Adapter initialization failed (init() or the adapter factory) |
ADAPTER_CLOSE |
Adapter close() failed |
QUERY_INVALID |
Invalid query shape (e.g., missing collection, non-object search, unknown operation name) |
TRANSACTION_FAILED |
Transaction failed |
TRANSACTION_ROLLBACK_FAILED |
Transaction failed and rollback failed |
REMOTE_ERROR |
Reserved; not emitted by the current core or remote client |
REMOTE_UNKNOWN |
Remote error response without a code field |
The values are exported as ErrorCodes from @wxn0brp/db-core/errors, with ErrorCode as the union type of all codes.
Error Classes
All classes extend ValtheraError, so a single isValtheraError(err) check covers them all.
| Class | Code | Thrown when |
|---|---|---|
ValtheraError |
(provided) | Base class; also used to rebuild remote errors |
UnsupportedOperationError |
UNSUPPORTED_OPERATION |
Operation not supported by the adapter (e.g., beginTransaction on a non-transactional adapter) |
QueryValidationError |
QUERY_INVALID |
Query shape is invalid (missing collection, non-object search/updater, unknown operation name, unsafe ID key, path traversal) |
AdapterError |
ADAPTER_ERROR |
Wrapper for adapter/driver errors raised during operations |
AdapterInitError |
ADAPTER_INIT |
Adapter init() or the adapter factory failed |
AdapterCloseError |
ADAPTER_CLOSE |
Adapter close() failed |
TransactionError |
TRANSACTION_FAILED / TRANSACTION_ROLLBACK_FAILED |
Transaction failed, handle mismatch, or failed rollback |
RemoteError |
REMOTE_ERROR |
Reserved; not thrown by the current implementation |
Error Structure
interface ValtheraErrorOpts {
code: string;
cause?: unknown;
suggestion?: string;
context?: Record<string, unknown>;
}
class ValtheraError extends Error {
code: string;
suggestion?: string;
context?: Record<string, unknown>;
toJSON(): {
name: string;
code: string;
message: string;
suggestion?: string;
context?: Record<string, unknown>;
};
}
Wrapping Behavior
- Adapter failures during operations are wrapped into
AdapterError, withop,collection(when the query has one) andadapter(the adapter version) added tocontext. If the adapter already throws aValtheraError, its class and code are kept and a copy with merged context is returned. On key collisions the error's existingcontextwins over the added keys, and the object identity changes. init()andclose()failures are wrapped intoAdapterInitErrorandAdapterCloseErrorinstead, unless the adapter throws aValtheraError.- When a non-
ValtheraErroris wrapped, the original error is available ascause. When an existingValtheraErroris copied, its prototype andcauseare preserved. - Remote clients always rebuild a base
ValtheraErrorfrom the server response (code,message,suggestion,context). The original subclass is not restored, and a response withoutcodebecomesREMOTE_UNKNOWN.
Working with Transactions
try {
await db.transaction(["accounts"], async tx => {
// ...
throw new Error("Payment failed");
});
} catch (err) {
// Rollback succeeded: the callback error is rethrown unchanged.
// TransactionError with TRANSACTION_ROLLBACK_FAILED: the rollback also failed.
}
A failure in beginTransaction or commitTransaction is wrapped like any other adapter operation, so it usually surfaces as AdapterError; some adapters, such as the directory adapter, throw TransactionError themselves. If the callback (or commit) fails and the rollback also fails, a TransactionError with code TRANSACTION_ROLLBACK_FAILED is thrown and the two errors are attached as an AggregateError in cause.