sequelize
>=6.28.1postconditions56functions37last verified2026-06-24coverage score100%Postconditions: what we check
- authenticate · connection-failureerrorWhenCannot connect to database (wrong credentials, host unreachable, etc.)Throws
ConnectionError, ConnectionRefusedError, HostNotFoundErrorRequired handlingCaller MUST catch connection errors. Common causes: wrong credentials, database down, network issues. Implement retry with exponential backoff for transient issues.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[1] - query · syntax-errorerrorWhenSQL syntax errorThrows
DatabaseError with original SQL error from underlying driverRequired handlingCaller MUST validate SQL syntax before execution. DO NOT retry - indicates SQL syntax error. Check error.original for underlying driver error.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[2] - query · constraint-violationerrorWhenUnique constraint, foreign key, or NOT NULL violationThrows
UniqueConstraintError, ForeignKeyConstraintError, ValidationErrorRequired handlingCaller MUST handle constraint violations gracefully. UniqueConstraintError: extract fields from error.fields. ForeignKeyConstraintError: check error.index. DO NOT retry without fixing data.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[3] - query · connection-errorerrorWhenConnection lost during query executionThrows
ConnectionError, TimeoutErrorRequired handlingCaller MUST handle connection errors separately from query errors. Implement retry with exponential backoff for transient connection issues.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[4] - findAll · query-failureerrorWhenNetwork error, timeout, or invalid queryThrows
DatabaseError, ConnectionError, TimeoutErrorRequired handlingCaller MUST catch query errors. Network errors may be transient and retriable. Invalid query errors should not be retried.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[5] - findOne · query-failureerrorWhenNetwork error, timeout, or invalid queryThrows
DatabaseError, ConnectionError, TimeoutErrorRequired handlingCaller MUST catch query errors. Returns null if no record matches (not an error). Network errors may be transient and retriable.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[5] - findByPk · query-failureerrorWhenNetwork error or timeoutThrows
DatabaseError, ConnectionError, TimeoutErrorRequired handlingCaller MUST catch query errors. Returns null if record not found (not an error).costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[6] - create · unique-constrainterrorWhenUnique constraint violationThrows
UniqueConstraintError with fields and error.errors arrayRequired handlingCaller MUST catch unique constraint errors. Extract conflicting fields from error.fields. DO NOT retry without changing unique field values.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[3] - create · validation-errorerrorWhenModel validation fails (NOT NULL, data type, etc.)Throws
ValidationError with error.errors arrayRequired handlingCaller MUST validate data before insert. Check error.errors for list of validation failures. DO NOT retry without fixing validation issues.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[3] - create · foreign-key-constrainterrorWhenForeign key constraint violationThrows
ForeignKeyConstraintErrorRequired handlingCaller MUST verify referenced record exists before insertion. DO NOT retry - indicates data integrity issue.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[3] - update · update-failureerrorWhenNetwork error, validation error, or constraint violationThrows
DatabaseError, ValidationError, UniqueConstraintErrorRequired handlingCaller MUST catch update errors. Validation errors: check error.errors array. Constraint violations: DO NOT retry without fixing data.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[5] - destroy · delete-failureerrorWhenNetwork error or foreign key constraintThrows
DatabaseError, ForeignKeyConstraintErrorRequired handlingCaller MUST catch delete errors. Foreign key errors: child records may still reference this record. Deleting non-existent record is NOT an error (returns 0).costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[5] - transaction · transaction-failureerrorWhenDeadlock, timeout, or constraint violation during transactionThrows
DatabaseError, TimeoutError, UniqueConstraintError, etc.Required handlingCaller MUST catch transaction errors and handle rollback. Sequelize auto-rollbacks on error in managed transactions. For unmanaged transactions, caller must explicitly rollback. Deadlocks may be transient and retriable.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[7] - sync · sync-failureerrorWhenSchema mismatch, permission denied, or connection errorThrows
DatabaseError, ConnectionErrorRequired handlingCaller MUST catch sync errors. NEVER use sync() in production - use migrations instead. sync() can drop and recreate tables - data loss risk.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[8] - count · count-failureerrorWhenNetwork error, timeout, or invalid queryThrows
DatabaseError, ConnectionError, TimeoutErrorRequired handlingCaller MUST catch count errors. Network errors may be transient and retriable.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[5] - bulkCreate · unique-constrainterrorWhenOne or more records violate unique constraintThrows
UniqueConstraintError — entire batch fails unless ignoreDuplicates option is setRequired handlingCaller MUST catch UniqueConstraintError. Use ignoreDuplicates: true to skip duplicates without throwing. Use updateOnDuplicate to upsert instead of error. Without these options, entire batch fails on first duplicate.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[9] - bulkCreate · validation-errorerrorWhenOne or more records fail model validationThrows
AggregateError containing ValidationError for each failed recordRequired handlingCaller MUST catch validation errors. Use validate: true (default) to validate all records before insert. Check error.errors for individual validation failures. Partial inserts may occur if validate option is false.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[3] - bulkCreate · connection-errorerrorWhenConnection lost during bulk insertThrows
ConnectionError, TimeoutErrorRequired handlingCaller MUST handle connection errors. Large bulk inserts are more likely to timeout. Consider chunking into smaller batches.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[4] - findOrCreate · unique-constraint-raceerrorWhenRace condition: concurrent findOrCreate calls create duplicateThrows
UniqueConstraintError when two concurrent calls both try to createRequired handlingCaller MUST catch UniqueConstraintError even though findOrCreate is designed to avoid it. Under concurrency, two calls may both fail the find and both attempt create. Retry the findOrCreate on UniqueConstraintError. Returns [instance, created] tuple.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible - findOrCreate · validation-errorerrorWhenDefaults fail model validationThrows
ValidationErrorRequired handlingCaller MUST catch ValidationError. The defaults object is used for creation — validate it.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[3] - findAndCountAll · query-failureerrorWhenNetwork error, timeout, or invalid queryThrows
DatabaseError, ConnectionError, TimeoutErrorRequired handlingCaller MUST catch query errors. Returns { count, rows }. count is total matching records, rows is the current page. Network errors may be transient.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[12] - upsert · validation-errorerrorWhenRecord fails model validationThrows
ValidationErrorRequired handlingCaller MUST catch ValidationError. Validate data before upsert. Check error.errors array.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[5] - upsert · connection-errorerrorWhenConnection lost during upsertThrows
DatabaseError, ConnectionError, TimeoutErrorRequired handlingCaller MUST handle connection errors. Upsert is atomic but connection loss mid-query is possible.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[4] - save · unique-constrainterrorWhenUnique constraint violation on saveThrows
UniqueConstraintErrorRequired handlingCaller MUST catch UniqueConstraintError. save() performs INSERT for new instances and UPDATE for existing ones. Both can trigger unique constraint violations.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[13] - save · validation-errorerrorWhenModel validation fails on saveThrows
ValidationError with error.errors arrayRequired handlingCaller MUST catch ValidationError. save() runs model validations before persisting. Check error.errors for individual validation failures.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[3] - save · optimistic-lock-errorerrorWhenConcurrent modification detected (optimistic locking)Throws
OptimisticLockError when version column mismatchRequired handlingCaller MUST catch OptimisticLockError if model uses version column. Reload instance and retry or inform user of conflict.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[14] - close · close-failureerrorWhenError while closing connection poolThrows
Error — underlying driver error during pool shutdownRequired handlingCaller MUST catch close errors during graceful shutdown. Failing to close leaks database connections. Call close() in process exit handlers (SIGTERM, SIGINT). After close(), all queries will fail with ConnectionError.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[15] - restore · restore-failureerrorWhenNetwork error or record not foundThrows
DatabaseError, ConnectionErrorRequired handlingCaller MUST catch restore errors. Only works on models with paranoid: true. Restoring non-existent record is not an error (updates 0 rows).costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[16] - increment · increment-failureerrorWhenNetwork error, invalid column, or record not foundThrows
DatabaseError, ConnectionErrorRequired handlingCaller MUST catch increment errors. Increment is atomic at the database level. Static version increments all matching records. Instance version increments the specific record.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[17] - decrement · decrement-failureerrorWhenNetwork error, invalid column, or record not foundThrows
DatabaseError, ConnectionErrorRequired handlingCaller MUST catch decrement errors. Decrement is atomic at the database level. Does NOT prevent negative values — add check constraints if needed.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[17] - truncate · truncate-failureerrorWhenForeign key constraint prevents truncationThrows
DatabaseError, ForeignKeyConstraintErrorRequired handlingCaller MUST catch truncate errors. TRUNCATE fails if other tables reference this table via FK. Use cascade: true option to truncate dependent tables. DANGEROUS in production — use with extreme caution.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[5] - reload · reload-deletederrorWhenRecord was deleted from database since last fetchThrows
InstanceError — record no longer existsRequired handlingCaller MUST catch errors when reloading. If the record was deleted between fetch and reload, Sequelize throws an error. Check instance existence first.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[18] - validate · validation-failureerrorWhenOne or more model validations failThrows
ValidationError with error.errors arrayRequired handlingCaller MUST catch ValidationError. validate() runs all model-level validations. Does NOT touch the database — only checks in-memory state. Useful for pre-flight validation before save().costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[3] - aggregate · query-failureerrorWhenNetwork error, timeout, or invalid column/functionThrows
DatabaseError, ConnectionError, TimeoutErrorRequired handlingCaller MUST catch aggregate errors. Invalid column name or aggregate function causes DatabaseError.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[5] - max · query-failureerrorWhenNetwork error or invalid columnThrows
DatabaseError, ConnectionErrorRequired handlingCaller MUST catch query errors. Returns null if no records match. Not an error.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[5] - min · query-failureerrorWhenNetwork error or invalid columnThrows
DatabaseError, ConnectionErrorRequired handlingCaller MUST catch query errors. Returns null if no records match. Not an error.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[5] - sum · query-failureerrorWhenNetwork error or invalid columnThrows
DatabaseError, ConnectionErrorRequired handlingCaller MUST catch query errors. Returns 0 if no records match. Not an error.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[5] - commit · commit-already-finishederrorWhenTransaction already committed or rolled backThrows
Error — 'Transaction cannot be committed because it has been finished with state: commit|rollback'Required handlingCaller MUST NOT call commit() more than once per transaction. MUST NOT call commit() after rollback(). Pattern: use try-catch-finally — rollback in catch, commit only in try. Calling commit() on a finished transaction throws a generic Error (not a Sequelize-specific subclass), so catch (err) will catch it.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible - commit · commit-database-errorerrorWhenDatabase connection lost or driver error during COMMITThrows
DatabaseError — underlying driver error; connection is force-cleanedRequired handlingCaller MUST catch errors from commit(). If commit() throws, the transaction is in an undetermined state and the connection is forcibly closed. The operation MAY or MAY NOT have committed on the database side. Check for idempotency before retrying. This is a critical edge case: data integrity may be uncertain.costhighin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[19] - rollback · rollback-already-finishederrorWhenTransaction already committed or rolled backThrows
Error — 'Transaction cannot be rolled back because it has been finished with state: commit|rollback'Required handlingCaller MUST NOT call rollback() on an already-finished transaction. MUST NOT call rollback() after commit() succeeds. Pattern: track whether commit() succeeded before calling rollback() in finally. Use a flag: let committed = false; try { await t.commit(); committed = true; } finally { if (!committed) await t.rollback(); }costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible - rollback · rollback-never-startederrorWhenTransaction was never started (no connection acquired)Throws
Error — 'Transaction cannot be rolled back because it never started'Required handlingCaller MUST ensure transaction was successfully initialized before rollback. This can happen if sequelize.transaction() itself threw during connection acquisition. Wrap the transaction initialization in try-catch as well.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[19] - rollback · rollback-database-errorerrorWhenDatabase driver error during ROLLBACKThrows
DatabaseError — driver error; connection force-cleanedRequired handlingCaller MUST catch errors from rollback(). If rollback() throws, the connection is forcibly killed. Always wrap rollback() in its own try-catch to avoid masking the original error. Do NOT let a rollback failure suppress the original transaction error.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[19] - instance.update · instance-update-unique-constrainterrorWhenUpdated value violates unique constraintThrows
UniqueConstraintError — same as save() since instance.update() delegates to save()Required handlingCaller MUST catch UniqueConstraintError. instance.update() internally calls save() — all save() error contracts apply. Extract conflicting fields from error.fields.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[13] - instance.update · instance-update-validation-errorerrorWhenUpdated values fail model validationThrows
ValidationError with error.errors arrayRequired handlingCaller MUST catch ValidationError. Model validations run before UPDATE query. Check error.errors array for individual field errors.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[3] - instance.update · instance-update-optimistic-lockerrorWhenConcurrent modification detected (optimistic locking enabled)Throws
OptimisticLockError when version column mismatch on saveRequired handlingCaller MUST catch OptimisticLockError if model uses version column. Reload instance and retry with fresh data or surface conflict to user.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[14] - instance.destroy · instance-destroy-foreign-keyerrorWhenOther records reference this instance via foreign key constraintThrows
ForeignKeyConstraintError — database rejects DELETE when child records existRequired handlingCaller MUST catch ForeignKeyConstraintError. Check error.index and error.table to identify referencing records. Delete or reassign child records first, or configure CASCADE in schema. instance.destroy() on paranoid models (soft-delete) does NOT trigger FK constraints — only hard-delete does.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible - instance.destroy · instance-destroy-connection-errorerrorWhenDatabase connection lost during DELETEThrows
DatabaseError, ConnectionErrorRequired handlingCaller MUST catch connection errors. The row may or may not have been deleted — check existence before retry.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[4] - findOrBuild · findorbuild-query-failureerrorWhenNetwork error or timeout during the find phaseThrows
DatabaseError, ConnectionError, TimeoutErrorRequired handlingCaller MUST catch query errors from findOrBuild(). The find phase can fail with any standard query error. If find fails, no instance is built. If build is needed after find, subsequent save() may throw UniqueConstraintError or ValidationError — handle those separately on save().costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[21] - findCreateFind · findcreatefind-validation-errorerrorWhenRecord to create fails model validationThrows
ValidationError — bubbles up from create() during the insert phaseRequired handlingCaller MUST catch ValidationError. If the find returns null and creation is attempted, validation runs. Unlike findOrCreate(), UniqueConstraintError is swallowed internally (retries find) but ValidationError propagates to the caller.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[3] - findCreateFind · findcreatefind-connection-errorerrorWhenNetwork error during find or create phasesThrows
DatabaseError, ConnectionError, TimeoutErrorRequired handlingCaller MUST catch connection errors. findCreateFind() does not wrap operations in a transaction — connection failure mid-operation leaves partial state risk (find succeeded, create failed).costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[4] - instance.restore · instance-restore-not-paranoiderrorWhenModel was not defined with paranoid: trueThrows
Error — 'Model is not paranoid' (synchronous throw, not a rejected Promise)Required handlingCaller MUST only call instance.restore() on paranoid models. Check model definition (paranoid: true) before calling restore(). This throws synchronously — not a rejected Promise.costlowin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[16] - instance.restore · instance-restore-connection-errorerrorWhenNetwork error during UPDATE to clear deletedAtThrows
DatabaseError, ConnectionErrorRequired handlingCaller MUST catch connection errors. The UPDATE to clear deletedAt may fail mid-flight.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[16] - instance.increment · instance-increment-db-errorerrorWhenDatabase connection failure or error during the UPDATE SQL. The instance already exists in memory — the error comes from the underlying UPDATE query. If the record was deleted between fetch and increment, no error is thrown — 0 rows are affected silently (UPDATE returns affectedRows: 0).Throws
DatabaseError, ConnectionError — same as Model.increment() since instance method delegates to staticRequired handlingCaller MUST wrap instance.increment() in try/catch. Common in background jobs that update counters (views, downloads, credits). Silent 0-row updates (deleted record) are NOT errors — check affectedRows if you need to detect phantom increments. Example: try { await post.increment('viewCount'); } catch (error) { if (error instanceof Sequelize.DatabaseError) { console.error('Increment failed:', error.message); } throw error; }costlowin prodimmediate exceptionusers seeservice unavailablevisibilityvisible - instance.decrement · instance-decrement-db-errorerrorWhenDatabase connection failure or driver error during the UPDATE SQL. The instance already exists in memory — the error comes from the underlying UPDATE query. If the record was deleted between fetch and decrement, no error is thrown — 0 rows are affected silently (UPDATE returns affectedRows: 0). Decrement does NOT enforce a floor — values can go negative unless the schema has a CHECK constraint that the database itself rejects.Throws
DatabaseError, ConnectionError — same as Model.decrement() since instance method delegates to staticRequired handlingCaller MUST wrap instance.decrement() in try/catch. Common in inventory/credit/quota systems that debit counters under load. A CHECK constraint violation (e.g. balance >= 0) surfaces as a DatabaseError — catching it is REQUIRED to convert into a domain "insufficient funds" response. Silent 0-row updates (deleted record) are NOT errors — check affectedRows if you need to detect phantom decrements. Example: try { await account.decrement('balance', { by: amount }); } catch (error) { if (error instanceof Sequelize.DatabaseError) { // Check constraint violation (e.g. balance < 0) lands here throw new InsufficientFundsError(error.message); } throw error; }costlowin prodimmediate exceptionusers seeservice unavailablevisibilityvisible - describe · describe-table-not-founderrorWhenThe model's table does not exist in the databaseThrows
Error — 'No description found for "<tableName>" table. Check the table name and schema; remember, they _are_ case sensitive.' NOTE: This is a generic Error, NOT a SequelizeDatabaseError. The error is NOT an instance of Sequelize.DatabaseError. Catching with instanceof Sequelize.BaseError will NOT catch it.Required handlingCaller MUST use try/catch and check error.message, not instanceof. describe() is commonly called in migration scripts and health checks to verify schema state. An uncaught table-not-found error crashes the script and makes migration status ambiguous. Example safe pattern: catch (error) { if (error.message.includes('No description found')) { ... } }costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[23] - describe · describe-connection-errorerrorWhenDatabase connection failure during DESCRIBE queryThrows
DatabaseError, ConnectionError (SequelizeDatabaseError, SequelizeConnectionError)Required handlingCaller MUST catch database and connection errors. describe() executes a real SQL query — it is not a local metadata lookup. A downed database or lost connection throws the same DatabaseError/ConnectionError hierarchy as findAll() or create().costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[1]
Sources
Every postcondition cites at least one of these. Grouped by source type; numbered to match the footnotes above.
- [1]sequelize.org/docs/v6/core-conceptsGetting Started
- [2]sequelize.org/docs/v6/core-conceptsRaw Queries
- [3]sequelize.org/docs/v6/core-conceptsValidations And Constraints
- [4]sequelize.org/docs/v6V6
- [5]sequelize.org/docs/v6/core-conceptsModel Querying Basics
- [6]sequelize.org/docs/v6/core-conceptsModel Querying Finders
- [7]sequelize.org/docs/v6/other-topicsTransactions
- [8]sequelize.org/docs/v6/core-conceptsModel Basics
- [9]sequelize.org/docs/v6/core-conceptsModel Querying Basics
- [10]sequelize.org/docs/v6/core-conceptsModel Querying Finders
- [12]sequelize.org/docs/v6/core-conceptsModel Querying Finders
- [13]sequelize.org/docs/v6/core-conceptsModel Instances
- [14]sequelize.org/docs/v6/other-topicsOptimistic Locking
- [15]sequelize.org/docs/v6/getting-startedGetting Started
- [16]sequelize.org/docs/v6/core-conceptsParanoid
- [17]sequelize.org/docs/v6/core-conceptsModel Instances
- [18]sequelize.org/docs/v6/core-conceptsModel Instances
- [20]sequelize.org/docs/v6/core-conceptsModel Instances
- [21]sequelize.org/docs/v6/core-conceptsModel Querying Finders
- [19]github.com/sequelize/sequelize/blobsequelize/sequelize · transaction.ts
- [22]github.com/sequelize/sequelize/blobsequelize/sequelize · model.js
- [23]github.com/sequelize/sequelize/blobsequelize/sequelize · query-interface.ts
- [11]github.com/sequelize/sequelize/issuessequelize/sequelize issue #4631
Research notes
Curator notes from SOURCES.md captured when the profile was written so you can verify the reasoning, not just the rules.
Sequelize Error Handling Reference
Package: sequelize Type: ORM (Object-Relational Mapping) Official Docs: https://sequelize.org/ GitHub: https://github.com/sequelize/sequelize npm: https://www.npmjs.com/package/sequelize
Overview
Sequelize is a promise-based Node.js ORM for Postgres, MySQL, MariaDB, SQLite, and Microsoft SQL Server. It features solid transaction support, relations, eager and lazy loading, read replication, and more. As an ORM that interacts with databases, Sequelize throws numerous error types that require proper handling.
Error Hierarchy
All Sequelize errors inherit from BaseError, which extends the native JavaScript Error object.
Complete Error Hierarchy:
BaseError (extends Error)
├── AggregateError
├── AssociationError
├── BulkRecordError
├── ConnectionError
│ ├── AccessDeniedError
│ ├── ConnectionAcquireTimeoutError
│ ├── ConnectionRefusedError
│ ├── ConnectionTimedOutError
│ ├── HostNotFoundError
│ ├── HostNotReachableError
│ └── InvalidConnectionError
├── DatabaseError
│ ├── ForeignKeyConstraintError
│ ├── TimeoutError
│ └── UniqueConstraintError
├── EagerLoadingError
├── EmptyResultError
├── InstanceError
├── OptimisticLockError
├── QueryError
├── SequelizeScopeError
└── ValidationError
├── UniqueConstraintError
└── ValidationErrorItem
Reference: https://sequelize.org/api/v7/hierarchy
Connection Errors
ConnectionError (Base Class)
Thrown when a connection to the database cannot be established.
Subclasses:
AccessDeniedError- Invalid credentialsConnectionAcquireTimeoutError- Connection pool timeoutConnectionRefusedError- Database refused connectionConnectionTimedOutError- Connection attempt timed outHostNotFoundError- Database host not foundHostNotReachableError- Database host unreachableInvalidConnectionError- Invalid connection configuration
Example:
try {
await sequelize.authenticate();
console.log('Connection has been established successfully.');
} catch (error) {
if (error instanceof ConnectionError) {
console.error('Unable to connect to the database:', error);
}
}
Configuration for Connection Pool:
const sequelize = new Sequelize('database', 'username', 'password', {
host: 'localhost',
dialect: 'postgres',
pool: {
max: 5,
min: 0,
acquire: 30000,
idle: 10000
}
});
Reference: https://sequelize.org/docs/v6/other-topics/connection-pool/
Database Errors
DatabaseError
Generic SQL errors thrown by the database.
Key Subclasses:
ForeignKeyConstraintErrorTimeoutErrorUniqueConstraintError
ForeignKeyConstraintError
Thrown when a foreign key constraint is violated in the database.
Properties:
fields- Array of field names involvedindex- Name of the constraintmessage- Error messageoriginal- Original database error
Example:
try {
await Order.create({
userId: 99999, // Non-existent user ID
product: 'Widget'
});
} catch (error) {
if (error instanceof ForeignKeyConstraintError) {
console.error('Foreign key violation:', error.fields);
// Handle invalid reference
}
}
Reference: https://sequelize.org/api/v7/classes/_sequelize_core.index.foreignkeyconstrainterror
TimeoutError
Thrown when a database query times out, typically due to a deadlock.
Properties:
sql- The SQL query that timed outparameters- Query parameterscause- Underlying error cause
Deadlock Example:
try {
await sequelize.transaction(async (t) => {
// Complex transaction that might deadlock
});
} catch (error) {
if (error instanceof TimeoutError) {
console.error('Transaction deadlock detected');
// Retry logic
}
}
Reference: https://sequelize.org/api/v7/classes/_sequelize_core.index.timeouterror
Validation Errors
ValidationError
Thrown when validation fails on model fields. Contains an errors property with an array of ValidationErrorItem objects.
Structure:
ValidationError {
name: 'SequelizeValidationError',
errors: [
ValidationErrorItem {
message: 'Validation notEmpty on email failed',
type: 'Validation error',
path: 'email',
value: '',
origin: 'FUNCTION',
instance: User {},
validatorKey: 'notEmpty',
validatorName: 'notEmpty',
validatorArgs: []
}
]
}
Example:
try {
await User.create({
email: '', // Violates notEmpty validation
age: -5 // Violates min validation
});
} catch (error) {
if (error instanceof ValidationError) {
error.errors.forEach(e => {
console.error(`${e.path}: ${e.message}`);
});
}
}
Reference: https://sequelize.org/api/v7/classes/_sequelize_core.index.validationerror
UniqueConstraintError
Thrown when a unique constraint is violated in the database. Extends both ValidationError and DatabaseError.
Properties:
errors- Array of ValidationErrorItem objectsfields- Object mapping field names to valuesparent- Original database errororiginal- Original database errorsql- SQL query that caused the error
Example:
try {
await User.create({
email: 'existing@example.com' // Email already exists
});
} catch (error) {
if (error instanceof UniqueConstraintError) {
console.error('Duplicate entry for:', Object.keys(error.fields));
// error.fields = { email: 'existing@example.com' }
}
}
Reference: https://sequelize.org/api/v7/classes/_sequelize_core.index.uniqueconstrainterror
Transaction Errors
Sequelize supports both managed and unmanaged transactions.
Managed Transactions (Recommended)
Automatically commit on success or rollback on error.
Pattern:
try {
const result = await sequelize.transaction(async (t) => {
const user = await User.create({ name: 'Alice' }, { transaction: t });
const account = await Account.create({ userId: user.id }, { transaction: t });
// If any error is thrown, transaction automatically rolls back
return { user, account };
});
console.log('Transaction committed:', result);
} catch (error) {
console.error('Transaction rolled back:', error);
}
Unmanaged Transactions
Manual commit/rollback control.
Pattern:
const t = await sequelize.transaction();
try {
const user = await User.create({ name: 'Alice' }, { transaction: t });
const account = await Account.create({ userId: user.id }, { transaction: t });
await t.commit();
console.log('Transaction committed');
} catch (error) {
await t.rollback();
console.error('Transaction rolled back:', error);
}
Reference: https://sequelize.org/docs/v6/other-topics/transactions/
Deadlock Handling
Configuration-Based Retry:
const sequelize = new Sequelize('database', 'username', 'password', {
retry: {
match: [
Sequelize.ConnectionError,
Sequelize.ConnectionTimedOutError,
Sequelize.TimeoutError,
/Deadlock/i,
'SQLITE_BUSY'
],
max: 3
}
});
Manual Retry Pattern:
async function retryTransaction(fn, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await sequelize.transaction(fn);
} catch (error) {
if (error instanceof TimeoutError && i < maxRetries - 1) {
console.warn(`Deadlock detected, retry ${i + 1}/${maxRetries}`);
continue;
}
throw error;
}
}
}
Reference: https://dev.to/anonyma/how-to-retry-transactions-in-sequelize-5h5c
Other Important Errors
EmptyResultError
Thrown when rejectOnEmpty mode is enabled and no record is found.
Example:
try {
const user = await User.findOne({
where: { id: 99999 },
rejectOnEmpty: true
});
} catch (error) {
if (error instanceof EmptyResultError) {
console.error('No user found');
}
}
Reference: https://sequelize.org/api/v7/classes/_sequelize_core.index.emptyresulterror
AggregateError
Wrapper for multiple errors that occurred during bulk operations.
Example:
try {
await User.bulkCreate([
{ email: 'user1@example.com' },
{ email: 'invalid-email' }, // Validation fails
{ email: 'user2@example.com' }
], { validate: true });
} catch (error) {
if (error instanceof AggregateError) {
error.errors.forEach(e => console.error(e.message));
}
}
Reference: https://sequelize.org/api/v7/classes/_sequelize_core.index.aggregateerror
Dangerous Operations
sync() - Production Warning
DO NOT use sync() in production!
sync()- Syncs all models to databasesync({ force: true })- DROPS ALL TABLES then recreatessync({ alter: true })- Alters tables to fit models (data loss risk)
Production Impact:
// ⚠️ DANGEROUS - Drops all tables and data!
await sequelize.sync({ force: true });
// ⚠️ DANGEROUS - May delete columns and data!
await sequelize.sync({ alter: true });
Recommended: Use Migrations for production schema changes.
Reference: https://sequelize.org/docs/v7/models/model-synchronization/
Common Pitfalls
1. Not Checking error.errors Array
Bad:
catch (error) {
console.error(error.message); // Loses validation details
}
Good:
catch (error) {
if (error instanceof ValidationError) {
error.errors.forEach(e => {
console.error(`${e.path}: ${e.message}`);
});
}
}
2. Forgetting Transaction Rollback
Bad (Unmanaged):
const t = await sequelize.transaction();
try {
await User.create({ name: 'Alice' }, { transaction: t });
// Error occurs, transaction never rolled back!
} catch (error) {
console.error(error); // Missing t.rollback()
}
Good:
const t = await sequelize.transaction();
try {
await User.create({ name: 'Alice' }, { transaction: t });
await t.commit();
} catch (error) {
await t.rollback();
throw error;
}
3. Using sync() in Production
Bad:
// Development
await sequelize.sync({ force: true }); // OK
// Production
await sequelize.sync({ force: true }); // ⚠️ DATA LOSS!
Good:
// Use migrations instead
npx sequelize-cli db:migrate
4. Not Handling Deadlocks
Bad:
await sequelize.transaction(async (t) => {
// Complex transaction
}); // No retry on deadlock
Good:
const sequelize = new Sequelize('db', 'user', 'pass', {
retry: {
match: [/Deadlock/i],
max: 3
}
});
Security Considerations
SQL Injection via Replacements
CVE-2023-25813 (CVSS 10.0) - Parameters in replacements are not properly escaped.
Affected: All versions < 6.19.1 Fixed: 6.19.1+
Vulnerable Code:
// ⚠️ VULNERABLE in versions < 6.19.1
await sequelize.query(
'SELECT * FROM users WHERE id = :id',
{
replacements: { id: userInput },
where: { status: 'active' }
}
);
Workaround: Don't use replacements and where in the same query.
Reference: https://github.com/advisories/GHSA-wrh9-cjv3-2hpw
Best Practices
- Always use try-catch around database operations
- Check error types using instanceof
- Use managed transactions when possible (auto-rollback)
- Configure retry logic for deadlocks
- Validate error.errors array for ValidationError/UniqueConstraintError
- Use migrations for production schema changes
- Never use sync({ force: true }) in production
- Update to latest version (6.19.1+ for security)
Minimum Safe Version
Recommended: sequelize@6.19.1 or later
This version fixes critical SQL injection vulnerability CVE-2023-25813.
Additional Resources
- Official Documentation: https://sequelize.org/docs/v6/
- Transactions Guide: https://sequelize.org/docs/v6/other-topics/transactions/
- Validations & Constraints: https://sequelize.org/docs/v6/core-concepts/validations-and-constraints/
- Error API Reference: https://sequelize.org/api/v7/hierarchy
- Security Advisories: https://github.com/sequelize/sequelize/security/advisories
- Migration Guide: https://sequelize.org/docs/v6/other-topics/migrations/