remix-run/remix · error · DataTableDatabaseError
Database execution failed
Error message
Database execution failed
What it means
This is the generic wrapper the Database puts around every driver.execute failure. The original error is preserved as cause, and metadata records the dialect and operation.kind, so you can inspect what dialect and what kind of operation (select/insert/update/...) failed. The underlying reason is almost always a SQL error: constraint violation, missing table/column, type mismatch, or syntax the driver rejected.
Source
Thrown at packages/data-table/src/lib/database.ts:970
}
if (failures.length > 1) {
throw new AggregateError(failures, 'Nested transaction cleanup failed', { cause: error })
}
throw error
}
await this.#driver.releaseSavepoint(this.#token, savepointName)
return result
}
async #executeOperation(operation: DataManipulationOperation): Promise<DataManipulationResult> {
try {
return await this.#driver.execute({
operation,
transaction: this.#token,
})
} catch (error) {
throw new DataTableDatabaseError('Database execution failed', {
cause: error,
metadata: {
dialect: this.dialect,
operationKind: operation.kind,
},
})
}
}
}
function defaultNow(): Date {
return new Date()
}
View on GitHub (pinned to 9696913134)
Solutions
- Inspect error.cause for the driver's real message (e.g. UNIQUE constraint failed) and fix the data or schema accordingly.
- Run migrations / verify the schema (db.migrationStatus()) if tables or columns are missing.
- For SQLite lock errors, serialize writes through a single connection/queue.
Example fix
// before
await db.create(users, values)
// after
try {
await db.create(users, values)
} catch (error) {
console.error(error.cause?.message, error.metadata)
throw error
} Defensive patterns
Strategy: try-catch
Validate before calling
// Catch at the boundary and surface the real cause
try {
await db.execute(operation)
} catch (error) {
throw new Response(error.cause?.message ?? 'Database error', { status: 500 })
} Type guard
function isDatabaseExecutionError(error: unknown): error is DataTableDatabaseError {
return error instanceof DataTableDatabaseError && error.message === 'Database execution failed'
} Try / catch
try {
await db.create(users, values)
} catch (error) {
if (isDatabaseExecutionError(error)) {
console.error(error.cause, error.metadata) // dialect + operationKind
}
throw error
} Prevention
- Run migrations before serving traffic; check migrationStatus in CI.
- Log error.cause, not the wrapper message, when debugging.
- Serialize SQLite writes to avoid 'database is locked'.
When it happens
Trigger: Any query/insert/update/delete whose compiled SQL fails: UNIQUE/FK/NOT NULL constraint violations, no such table (migrations not run), no such column (schema drift), locked database, or invalid values.
Common situations: Running against a database missing migrations; schema changes not applied in an environment; constraint violations on inserts; SQLite 'database is locked' under concurrent writers.
Related errors
- MySQL database + method + () requires config-based construc
- create({ returnRow: true }) failed to return an inserted row
- Unknown transaction token: + token.id
- MySQL migration lock is already held by this database
- MySQL database cannot + method + while transactions are op
AI-assisted analysis of remix-run/remix@9696913134 (2026-08-27).
Data as JSON: /api/errors/591242c083003c4c.
Report an issue: GitHub.