n8n-io/n8n · error · TypeORMError
Sqlite does not support AUTOINCREMENT on composite primary k
Error message
Sqlite does not support AUTOINCREMENT on composite primary key
What it means
SQLite only permits AUTOINCREMENT on a single INTEGER PRIMARY KEY column. createTableSql() detects a composite primary key (more than one primary column) where at least one column is generated with the 'increment' strategy, and throws TypeORMError before generating any DDL. This is a schema-design constraint enforced up front.
Source
Thrown at packages/@n8n/typeorm/src/driver/sqlite-abstract/AbstractSqliteQueryRunner.ts:1486
}),
);
}
/**
* Builds create table sql.
*/
protected createTableSql(
table: Table,
createForeignKeys?: boolean,
temporaryTable?: boolean,
): Query {
const primaryColumns = table.columns.filter((column) => column.isPrimary);
const hasAutoIncrement = primaryColumns.find(
(column) => column.isGenerated && column.generationStrategy === 'increment',
);
const skipPrimary = primaryColumns.length > 1;
if (skipPrimary && hasAutoIncrement)
throw new TypeORMError(`Sqlite does not support AUTOINCREMENT on composite primary key`);
const columnDefinitions = table.columns
.map((column) => this.buildCreateColumnSql(column, skipPrimary))
.join(', ');
const [database] = this.splitTablePath(table.name);
let sql = `CREATE TABLE ${this.escapePath(table.name)} (${columnDefinitions}`;
let [databaseNew, tableName] = this.splitTablePath(table.name);
const newTableName = temporaryTable
? `${databaseNew ? `${databaseNew}.` : ''}${tableName.replace(/^temporary_/, '')}`
: table.name;
// need for `addColumn()` method, because it recreates table.
table.columns
.filter((column) => column.isUnique)
.forEach((column) => {
const isUniqueExist = table.uniques.some(
(unique) => unique.columnNames.length === 1 && unique.columnNames[0] === column.name,View on GitHub (pinned to 5ac6606e81)
Solutions
- Split the auto-increment column out of the composite key — on SQLite it must be the sole primary column.
- For composite keys, drop the auto-increment strategy and assign IDs manually (or use a sequence/trigger).
- Redesign the entity so only one column is PRIMARY KEY if you need AUTOINCREMENT.
- If multi-column uniqueness is what you need, keep a single auto-increment PK and add a separate composite unique index instead.
Example fix
// before — composite PK with one auto-increment column
@PrimaryGeneratedColumn({ strategy: 'increment' })
id: number;
@PrimaryColumn() tenantId: number;
// after — single auto-increment PK, composite uniqueness via index
@PrimaryGeneratedColumn({ strategy: 'increment' })
id: number;
@Column() tenantId: number;
@Index('UQ_tenant_id', ['id', 'tenantId'], { unique: true }) Defensive patterns
Strategy: validation
Validate before calling
function isValidSqlitePrimaryKey(columns: { isPrimary: boolean; isGenerated: boolean; generationStrategy?: string }[]): boolean {
const primaries = columns.filter((c) => c.isPrimary);
const autoInc = primaries.some(
(c) => c.isGenerated && c.generationStrategy === 'increment',
);
return !(primaries.length > 1 && autoInc);
}
if (!isValidSqlitePrimaryKey(entityColumns)) {
throw new Error('SQLite cannot combine AUTOINCREMENT with a composite primary key');
} Type guard
const hasCompositeAutoIncrementPk = (table: Table): boolean => {
const primaries = table.columns.filter((c) => c.isPrimary);
const autoInc = primaries.some(
(c) => c.isGenerated && c.generationStrategy === 'increment',
);
return primaries.length > 1 && autoInc;
}; Prevention
- On SQLite, keep AUTOINCREMENT on a single INTEGER PRIMARY KEY column.
- Model composite uniqueness with a separate unique index, not a composite PK.
- Validate entity metadata against driver capabilities before sync.
When it happens
Trigger: Creating/recreating a table (CREATE TABLE path, including the table-copy used by ALTER workarounds) whose entity/metadata marks multiple columns as @PrimaryColumn and one of them as @PrimaryGeneratedColumn({ strategy: 'increment' }) / generationStrategy 'increment'.
Common situations: Porting a Postgres schema with a composite PK plus a serial column to SQLite; entities using a composite key that also mark an id column as auto-increment; test fixtures mirroring such a schema on SQLite.
Related errors
- 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
- Transaction rollback failed
- Stream is not supported by sqlite driver.
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/0a26a422daad5c57.
Report an issue: GitHub.