Error handling & error types
Read this page in the documentation
Error handling & error types Every failure prorm raises is an instance of a single base class, PrormError, which itself extends the native Error. Driver-level failures (a dropped connection, a violated constraint, a locked table) are normalized into typed subclasses so you can branch on the kind of failure instead of pattern-matching raw driver message strings. This guide covers the class hierarchy that actually exists in src/errors, how to catch and tell the errors apart, the properties each one carries, and the utility helpers for classifying, retrying, and formatting them. Everything documented here is exported from the package root: The class hierarchy PrormError is the root. Most typed errors extend it directly; the constraint errors are the one place the tree goes deeper — UniqueConstraintError extends ValidationError (a unique violation is a kind of validation failure), while ForeignKeyConstraintError and ExclusionConstraintError extend PrormError directly. Because everything descends from PrormError, a single instanceof PrormError check separates prorm-originated failures from unexpected bugs in your own code. Error types Class | Extends | Default code | Notable properties | --------------------------- | ----------------- | ------------------------------ | -------------------------------------- | PrormError | Error | UNKNOWN | code, parent, sql, metadata | ConnectionError | PrormError | CONNECTIONERROR | database, host | DatabaseError | PrormError | DATABASEERROR | original | ValidationError | PrormError | VALIDATIONERROR | errors[] | UniqueConstraintError | ValidationError | VALIDATIONERROR | fields[], errors[] | ForeignKeyConstraintError | PrormError | FOREIGNKEYCONSTRAINTERROR | field, table, value | ExclusionConstraintError | PrormError | EXCLUSIONCONSTRAINTERROR | constraint | TimeoutError | PrormError | TIMEOUTERROR | timeout | ResourceLockedError | PrormError | RESOURCELOCKEDERROR | resource | BulkRecordError | PrormError | BULKRECORDERROR | errors[], errorCount | AssociationError | PrormError | ASSOCIATIONERROR | association | EmptyResultError | PrormError | UNKNOWN | model, primaryKey, where | Common properties Every PrormError carries the same base set of fields, so any handler that catches the base type can rely on them: toJSON() is defined on the base class, so any prorm error serializes cleanly for structured logging: Catching and distinguishing errors Use instanceof to branch on error type. Because PrormError is the root, check specific subclasses first and fall back to the base type: Order matters: UniqueConstraintError extends ValidationError, so a ValidationError check placed first would swallow it. Type guards For narrowing in TypeScript without remembering the hierarchy, prorm ships guard functions that both check the type and narrow it: Matching by error code Every error carries a stable code from the ErrorCodes map. Codes are useful when you want to route on a specific condition without importing the class — for example distinguishing a refused connection from a timed-out one, both of which are ConnectionError: Handling validation errors ValidationError collects one or more ValidationErrorItem entries in its errors array. Each item records the message, type, and — when the failure is tied to a field — the path, value, and validator. Two helpers make the array easy to consume: UniqueConstraintError is a specialization of ValidationError, so it exposes the same errors array plus a fields list naming the columns that collided: Handling database & constraint errors When a query reaches the driver and fails, the raw driver error is normalized by wrapError into the most specific prorm type it can identify from the message — a foreign-key violation becomes ForeignKeyConstraintError, a duplicate becomes UniqueConstraintError, a lock becomes ResourceLockedError, and anything unrecognized falls back to a generic DatabaseError. The original driver error is always preserved on .parent, and DatabaseError additionally keeps its text on .original. You can also invoke the wrapper directly if you catch a raw driver error yourself: Bulk operations BulkRecordError aggregates per-record failures from a batch operation. Each entry pairs the failing record's index, the record itself, and its error: Handling connection errors ConnectionError records the database and host it was trying to reach, and its code distinguishes the failure mode. The class provides static factories that set the right code for you — these are what the internal connection handling uses: At the catch site you usually only care whether to retry: Missing-result errors findByPk / findOne style lookups that expect a row but find none raise EmptyResultError, which remembers what was searched for. Its getMessage() builds a descriptive sentence from whichever of model, primaryKey, and where are set: Retrying transient failures Not every error is worth retrying. isRetryableError returns true only for the transient classes — every TimeoutError and ResourceLockedError, plus ConnectionErrors whose code is CONNECTIONTIMEDOUT or HOSTNOTREACHABLE. Constraint and validation failures are deterministic and are never retryable. Logging & unwrapping helpers Two more utilities round out a handler. getRootCause unwraps the .parent chain to the original driver error, and formatError renders any error — including the nested validation items — into a multi-line log string. Constructing validation errors When writing custom validators you can build errors with the same shape prorm uses internally. createValidationError makes a single-item error, and aggregateErrors merges several sources (existing ValidationErrors, item arrays, raw Errors, or strings) into one: Summary Catch PrormError to separate prorm failures from unexpected bugs, then narrow to specific subclasses. Check the deepest subclass first — UniqueConstraintError before ValidationError. Read code for a stable, class-independent switch; read parent / sql / original for the underlying driver detail. Use isRetryableError to decide what to retry, and formatError / getRootCause when logging. Related reading Core concepts — the reading path these belong to Going further — the specialised material