Skip to content
result-rpc
Esc
navigateopen⌘Jpreview
On this page

Database errors

Turn common database constraint failures into private tagged values.

result-rpc/db provides an ORM-independent Result boundary for database operations. tryDb accepts any thenable—or a thunk for drivers that may throw while preparing a query—and classifies common SQLite and PostgreSQL failures:

import { tryDb } from "result-rpc/db";

const inserted = await tryDb(db.insert(reviews).values(row).returning());
if (!inserted.ok) {
  return matchError(inserted.error, {
    "db/unique-violation": () => err(errors.alreadyReviewed({ hotelId })),
    "db/foreign-key-violation": () => err(errors.hotelNotFound({ hotelId })),
    "db/not-null-violation": () => err(errors.invalid({})),
    "db/check-violation": () => err(errors.invalid({})),
    "db/query-failure": () => err(errors.unavailable({})),
  });
}

Attempting the insert is the uniqueness check. Unlike a SELECT-first check, the constraint remains correct when two requests race.

Private composition currency

Every db/* error is private. It belongs inside server implementation code, not in a procedure’s declared wire union:

Tag Meaning
db/unique-violation A unique or primary-key constraint hit
db/foreign-key-violation A referenced row does not exist
db/not-null-violation A required value was absent
db/check-violation A database check rejected the value
db/query-failure No more specific classification

Collapse that vocabulary into the procedure’s domain errors at the handler boundary. An uncollapsed database error is rejected by the contract and sanitized to server/internal rather than leaking driver details.

Cause retention

The tagged database error retains the original failure locally as its standard, non-enumerable Error.cause. tryDb follows ordinary cause chains and the common payload slots used by Effect Cause, allowing it to see through ORM and driver wrappers.

The cause is diagnostic context only. SQL text, parameters, driver internals, and the cause itself are absent from toJSON(), encoded Results, and RPC responses.

Was this page helpful?