n8n-io/n8n · error · TransactionRollbackFailedError
Transaction rollback failed
Error message
Transaction rollback failed
What it means
Thrown by the abstract SQLite query runner when the underlying `ROLLBACK` (or `ROLLBACK TO SAVEPOINT`) SQL statement itself fails inside rollbackTransaction(). The original driver error is passed as `error.cause` (see TransactionRollbackFailedError). It means SQLite could not undo the transaction — almost always a low-level I/O or connection-state problem, not a bug in your migration logic.
Source
Thrown at packages/@n8n/typeorm/src/driver/sqlite-abstract/AbstractSqliteQueryRunner.ts:156
*/
async rollbackTransaction(): Promise<void> {
try {
if (!this.isTransactionActive) throw new TransactionNotStartedError();
await this.broadcaster.broadcast('BeforeTransactionRollback');
if (this.transactionDepth > 1) {
this.transactionDepth -= 1;
await this.query(`ROLLBACK TO SAVEPOINT typeorm_${this.transactionDepth}`);
} else {
this.transactionDepth -= 1;
await this.query('ROLLBACK');
this.isTransactionActive = false;
}
await this.broadcaster.broadcast('AfterTransactionRollback');
} catch (rollbackError) {
throw new TransactionRollbackFailedError(rollbackError);
}
}
/**
* Returns raw data stream.
*/
stream(
query: string,
parameters?: any[],
onEnd?: Function,
onError?: Function,
): Promise<ReadStream> {
throw new TypeORMError(`Stream is not supported by sqlite driver.`);
}
/**
* Returns all available database names including system databases.
*/View on GitHub (pinned to 5ac6606e81)
Solutions
- Inspect `error.cause` for the real SQLite error code/message (SQLITE_IOERR, SQLITE_BUSY, 'no such savepoint', 'database is locked') and address that root cause.
- Keep the DB file on stable local storage for the process lifetime.
- If triggered by a failed prior statement, fix that statement so the transaction stays valid.
- Re-open the DataSource / restart the process — after a failed rollback the connection is typically wedged and must not be reused.
Example fix
// before
await queryRunner.rollbackTransaction();
// after
try {
await queryRunner.rollbackTransaction();
} catch (e) {
if (e instanceof TransactionRollbackFailedError) {
logger.error('rollback failed', { cause: e.cause });
await dataSource.destroy(); // connection is unusable
}
throw e;
} Defensive patterns
Strategy: try-catch
Validate before calling
// No safe pre-check: rollback fails at the SQL layer.
// Ensure the connection is healthy before attempting:
if (!queryRunner.connection.isInitialized) {
throw new Error('DataSource not initialized — cannot rollback');
} Type guard
import { TypeORMError } from '@n8n/typeorm';
function isTransactionRollbackFailedError(e: unknown): e is TypeORMError & { cause: unknown } {
return e instanceof TypeORMError && e.message === 'Transaction rollback failed';
} Try / catch
try {
await queryRunner.rollbackTransaction();
} catch (e) {
if (isTransactionRollbackFailedError(e)) {
logger.error('sqlite rollback failed', { cause: e.cause });
// connection is wedged — tear it down
await dataSource.destroy().catch(() => {});
}
throw e;
} Prevention
- Keep the SQLite file on local, stable storage.
- Avoid long-running transactions that increase exposure to I/O or lock failures.
- Don't manipulate the underlying sqlite3 connection behind TypeORM's back.
- Log error.cause — the real SQLite code is the actionable signal.
When it happens
Trigger: Calling queryRunner.rollbackTransaction() on a SQLite AbstractSqliteQueryRunner after the connection hit a disk I/O error, the DB file was removed/unreachable, or an earlier statement already broke the transaction. Also when a nested savepoint rollback fails (transactionDepth > 1, e.g. 'no such savepoint: typeorm_0').
Common situations: SQLite DB file on an unreliable/network mount, disk full, file deleted or moved while the process runs, concurrent write-lock escalation corrupting txn state, or code that manually fiddles with the same sqlite3 connection outside TypeORM.
Related errors
- Transaction commit 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/f86cdc0c305375df.
Report an issue: GitHub.