n8n-io/n8n · error · TransactionCommitFailedError
Transaction commit failed
Error message
Transaction commit failed
What it means
Thrown by the pooled SQLite read/write runner when the `COMMIT` SQL statement itself fails inside commitTransaction(). The original error is passed as `error.cause` (see TransactionCommitFailedError). On failure the runner marks the leased connection invalid and releases the lease in a finally block, so the transaction is over but its effects are not guaranteed durable.
Source
Thrown at packages/@n8n/typeorm/src/driver/sqlite-pooled/SqliteReadWriteQueryRunner.ts:127
}
/**
* Commits transaction.
* Error will be thrown if transaction was not started.
*/
async commitTransaction(): Promise<void> {
if (!this.isTransactionActive) throw new TransactionNotStartedError();
if (!this.trxDbLease) throw new TransactionNotStartedError();
try {
await this.broadcaster.broadcast('BeforeTransactionCommit');
await this.runQueryWithinConnection(this.trxDbLease.connection, 'COMMIT');
await this.broadcaster.broadcast('AfterTransactionCommit');
} catch (commitError) {
this.trxDbLease.markAsInvalid();
throw new TransactionCommitFailedError(commitError);
} finally {
this.releaseTrxDbLease();
}
}
/**
* Rollbacks transaction.
* Error will be thrown if transaction was not started.
*/
async rollbackTransaction(): Promise<void> {
if (!this.isTransactionActive) throw new TransactionNotStartedError();
if (!this.trxDbLease) throw new TransactionNotStartedError();
try {
await this.broadcaster.broadcast('BeforeTransactionRollback');
await this.runQueryWithinConnection(this.trxDbLease.connection, 'ROLLBACK');
View on GitHub (pinned to 5ac6606e81)
Solutions
- Inspect `error.cause` for the real SQLite code (SQLITE_BUSY, SQLITE_IOERR, SQLITE_CONSTRAINTFK) and address that root cause.
- Widen the busy timeout / shorten transactions to reduce SQLITE_BUSY on commit.
- Ensure the DB file is on stable local storage.
- Treat the connection as spent — the lease is released and marked invalid; open a fresh transaction rather than reusing state.
Example fix
// before
await queryRunner.commitTransaction();
// after
try {
await queryRunner.commitTransaction();
} catch (e) {
if (e instanceof TransactionCommitFailedError) {
logger.error('commit failed', { cause: e.cause });
}
throw e;
} Defensive patterns
Strategy: try-catch
Validate before calling
// No safe pre-check: COMMIT fails at the SQL layer.
// Reduce SQLITE_BUSY by setting a busy timeout before transactions:
await queryRunner.query('PRAGMA busy_timeout = 5000'); Type guard
import { TypeORMError } from '@n8n/typeorm';
function isTransactionCommitFailedError(e: unknown): e is TypeORMError & { cause: unknown } {
return e instanceof TypeORMError && e.message === 'Transaction commit failed';
} Try / catch
try {
await queryRunner.commitTransaction();
} catch (e) {
if (isTransactionCommitFailedError(e)) {
logger.error('sqlite commit failed', { cause: e.cause });
}
throw e;
} Prevention
- Set PRAGMA busy_timeout to tolerate brief lock contention.
- Keep transactions short to reduce commit-time failures.
- Keep the DB file on stable local storage.
- Treat the leased connection as spent after a failed commit.
When it happens
Trigger: Calling commitTransaction() on a SqliteReadWriteQueryRunner when the COMMIT hits SQLITE_BUSY/SQLITE_IOERR, the DB file became unreachable mid-transaction, the connection lease was invalidated by a prior statement error, or a constraint violation surfaced only at commit.
Common situations: Concurrent writers causing lock contention, DB file on an unreliable mount, disk full at commit time, or a deferred-FK violation that SQLite checks at commit.
Related errors
- Transaction rollback failed
- Transaction rollback failed
- SQLite package has not been found installed. Try to install
- Transactions aren't supported by ${this.connection.driver.op
- SQLite only supports SERIALIZABLE and READ UNCOMMITTED isola
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/440265acc5d00000.
Report an issue: GitHub.