{"record":{"id":"440265acc5d00000","repo":"n8n-io/n8n","slug":"transaction-commit-failed","errorCode":null,"errorMessage":"Transaction commit failed","messagePattern":"Transaction commit failed","errorType":"exception","errorClass":"TransactionCommitFailedError","httpStatus":null,"severity":"error","filePath":"packages/@n8n/typeorm/src/driver/sqlite-pooled/SqliteReadWriteQueryRunner.ts","lineNumber":127,"sourceCode":"\t}\n\n\t/**\n\t * Commits transaction.\n\t * Error will be thrown if transaction was not started.\n\t */\n\tasync commitTransaction(): Promise<void> {\n\t\tif (!this.isTransactionActive) throw new TransactionNotStartedError();\n\t\tif (!this.trxDbLease) throw new TransactionNotStartedError();\n\n\t\ttry {\n\t\t\tawait this.broadcaster.broadcast('BeforeTransactionCommit');\n\n\t\t\tawait this.runQueryWithinConnection(this.trxDbLease.connection, 'COMMIT');\n\n\t\t\tawait this.broadcaster.broadcast('AfterTransactionCommit');\n\t\t} catch (commitError) {\n\t\t\tthis.trxDbLease.markAsInvalid();\n\t\t\tthrow new TransactionCommitFailedError(commitError);\n\t\t} finally {\n\t\t\tthis.releaseTrxDbLease();\n\t\t}\n\t}\n\n\t/**\n\t * Rollbacks transaction.\n\t * Error will be thrown if transaction was not started.\n\t */\n\tasync rollbackTransaction(): Promise<void> {\n\t\tif (!this.isTransactionActive) throw new TransactionNotStartedError();\n\t\tif (!this.trxDbLease) throw new TransactionNotStartedError();\n\n\t\ttry {\n\t\t\tawait this.broadcaster.broadcast('BeforeTransactionRollback');\n\n\t\t\tawait this.runQueryWithinConnection(this.trxDbLease.connection, 'ROLLBACK');\n","sourceCodeStart":109,"sourceCodeEnd":145,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/@n8n/typeorm/src/driver/sqlite-pooled/SqliteReadWriteQueryRunner.ts#L109-L145","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nawait queryRunner.commitTransaction();\n\n// after\ntry {\n  await queryRunner.commitTransaction();\n} catch (e) {\n  if (e instanceof TransactionCommitFailedError) {\n    logger.error('commit failed', { cause: e.cause });\n  }\n  throw e;\n}","handlingStrategy":"try-catch","validationCode":"// No safe pre-check: COMMIT fails at the SQL layer.\n// Reduce SQLITE_BUSY by setting a busy timeout before transactions:\nawait queryRunner.query('PRAGMA busy_timeout = 5000');","typeGuard":"import { TypeORMError } from '@n8n/typeorm';\n\nfunction isTransactionCommitFailedError(e: unknown): e is TypeORMError & { cause: unknown } {\n  return e instanceof TypeORMError && e.message === 'Transaction commit failed';\n}","tryCatchPattern":"try {\n  await queryRunner.commitTransaction();\n} catch (e) {\n  if (isTransactionCommitFailedError(e)) {\n    logger.error('sqlite commit failed', { cause: e.cause });\n  }\n  throw e;\n}","preventionTips":["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."],"tags":["database","transaction","sqlite"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}