n8n-io/n8n · error · TypeORMError

Transactions aren't supported by ${this.connection.driver.op

Error message

Transactions aren't supported by ${this.connection.driver.options.type}.

What it means

TypeORMError('Transactions aren't supported by ${driver.options.type}') is raised in AbstractSqliteQueryRunner.startTransaction when driver.transactionSupport === 'none'. The sqlite (legacy) driver declares transactionSupport as 'none', so any attempt to start a transaction through it fails immediately.

Source

Thrown at packages/@n8n/typeorm/src/driver/sqlite-abstract/AbstractSqliteQueryRunner.ts:74

		return Promise.resolve(this.driver.databaseConnection);
	}

	/**
	 * Releases used database connection.
	 * We just clear loaded tables and sql in memory, because sqlite do not support multiple connections thus query runners.
	 */
	release(): Promise<void> {
		this.loadedTables = [];
		this.clearSqlMemory();
		return Promise.resolve();
	}

	/**
	 * Starts transaction.
	 */
	async startTransaction(isolationLevel?: IsolationLevel): Promise<void> {
		if (this.driver.transactionSupport === 'none')
			throw new TypeORMError(
				`Transactions aren't supported by ${this.connection.driver.options.type}.`,
			);

		if (this.isTransactionActive && this.driver.transactionSupport === 'simple')
			throw new TransactionAlreadyStartedError();

		if (
			isolationLevel &&
			isolationLevel !== 'READ UNCOMMITTED' &&
			isolationLevel !== 'SERIALIZABLE'
		)
			throw new TypeORMError(`SQLite only supports SERIALIZABLE and READ UNCOMMITTED isolation`);

		this.isTransactionActive = true;
		try {
			await this.broadcaster.broadcast('BeforeTransactionStart');
		} catch (err) {
			this.isTransactionActive = false;

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Switch the driver to 'sqlite-pooled' (DB_TYPE=sqlite-pooled), which supports transactions and is the recommended local-dev driver.
  2. If you must stay on legacy sqlite, refactor the code to not use explicit transactions (single statements are atomic; multi-statement atomicity is not guaranteed).
  3. Use postgres for any environment where transactional integrity is required.
  4. Check driver.transactionSupport at runtime before calling startTransaction to fail gracefully.

Example fix

// before
DB_TYPE=sqlite
await ds.transaction(async (qr) => { ... });  // fails
// after
DB_TYPE=sqlite-pooled
await ds.transaction(async (qr) => { ... });
Defensive patterns

Strategy: validation

Validate before calling

const SUPPORTS_TX = new Set(['postgres', 'sqlite-pooled']);
function assertTransactionsSupported(driverType: string): void {
  if (!SUPPORTS_TX.has(driverType)) {
    throw new Error(`Driver '${driverType}' does not support transactions; use sqlite-pooled or postgres.`);
  }
}

Type guard

function driverSupportsTransactions(driver: { transactionSupport?: string }): boolean {
  return driver.transactionSupport !== 'none';
}

Try / catch

import { TypeORMError } from '@n8n/typeorm';
try {
  await dataSource.transaction(async (qr) => { /* ... */ });
} catch (e) {
  if (e instanceof TypeORMError && /Transactions aren't supported/.test(e.message)) {
    throw new Error('Current driver has no transaction support; switch DB_TYPE to sqlite-pooled or postgres.');
  }
  throw e;
}

Prevention

When it happens

Trigger: Code calls queryRunner.startTransaction() (or DataSource.transaction()) while the driver is the legacy non-pooled sqlite driver whose transactionSupport is 'none'. The 'sqlite-pooled' driver supports transactions, the plain 'sqlite' driver does not.

Common situations: A default local install uses DB_TYPE=sqlite (legacy) but business logic attempts a transactional unit of work; code that worked against postgres is run against sqlite; a library assumes transaction support without checking.

Related errors


AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12). Data as JSON: /api/errors/d109082f51f30146. Report an issue: GitHub.