n8n-io/n8n · error · TypeORMError
SQLite only supports SERIALIZABLE and READ UNCOMMITTED isola
Error message
SQLite only supports SERIALIZABLE and READ UNCOMMITTED isolation
What it means
TypeORMError('SQLite only supports SERIALIZABLE and READ UNCOMMITTED isolation') is raised in startTransaction when an isolationLevel is requested that is neither 'READ UNCOMMITTED' nor 'SERIALIZABLE'. SQLite's isolation model only exposes these two levels, so requesting READ COMMITTED or REPEATABLE READ is rejected.
Source
Thrown at packages/@n8n/typeorm/src/driver/sqlite-abstract/AbstractSqliteQueryRunner.ts:86
/**
* 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;
throw err;
}
if (this.transactionDepth === 0) {
this.transactionDepth += 1;
if (isolationLevel) {
if (isolationLevel === 'READ UNCOMMITTED') {
await this.query('PRAGMA read_uncommitted = true');
} else {
await this.query('PRAGMA read_uncommitted = false');
}
}View on GitHub (pinned to 5ac6606e81)
Solutions
- Pass undefined (no isolation level) or one of 'READ UNCOMMITTED' / 'SERIALIZABLE' when running against sqlite.
- Make the isolation level configurable per-environment and omit it for sqlite.
- Use postgres for environments that genuinely need READ COMMITTED / REPEATABLE READ semantics.
- Guard the call: check the driver type before requesting a level.
Example fix
// before
await qr.startTransaction('READ COMMITTED'); // fails on sqlite
// after
const level = driver.options.type.startsWith('sqlite') ? undefined : 'READ COMMITTED';
await qr.startTransaction(level);
Defensive patterns
Strategy: validation
Validate before calling
const SQLITE_LEVELS = new Set(['READ UNCOMMITTED', 'SERIALIZABLE']);
function pickIsolationLevel(level, driverType): string | undefined {
if (!level) return undefined;
if (driverType.startsWith('sqlite') && !SQLITE_LEVELS.has(level)) return undefined;
return level;
}
Type guard
const SQLITE_ISOLATION_LEVELS = ['READ UNCOMMITTED', 'SERIALIZABLE'] as const;
function isSqliteIsolationLevel(x: unknown): x is (typeof SQLITE_ISOLATION_LEVELS)[number] {
return typeof x === 'string' && (SQLITE_ISOLATION_LEVELS as readonly string[]).includes(x);
}
Try / catch
import { TypeORMError } from '@n8n/typeorm';
try {
await qr.startTransaction(requestedLevel);
} catch (e) {
if (e instanceof TypeORMError && /SQLite only supports/.test(e.message)) {
// retry without an isolation level on sqlite
await qr.startTransaction(undefined);
} else {
throw e;
}
}
Prevention
- Do not request READ COMMITTED / REPEATABLE READ against sqlite.
- Make isolation level env-aware and omit it for sqlite.
- Add a unit test matrix covering sqlite + each isolation level.
- Document the two-level SQLite isolation model for developers.
When it happens
Trigger: Caller invokes startTransaction('READ COMMITTED') or startTransaction('REPEATABLE READ') against a sqlite-family driver. The guard fires before any SQL is issued.
Common situations: Code written for postgres (which accepts the full isolation ladder) is reused against sqlite; a generic helper passes a default isolation level without driver-awareness; tests run against sqlite but production uses postgres.
Related errors
- Transactions aren't supported by ${this.connection.driver.op
- SQLite package has not been found installed. Try to install
- Wrong driver: "${driverType}" given. Supported drivers are:
- Driver not Connected
- To use streams you should install pg-query-stream package. P
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/21d33d7e65b28371.
Report an issue: GitHub.