n8n-io/n8n · error · TypeORMError

onUpdate is not supported by the current database driver

Error message

onUpdate is not supported by the current database driver

What it means

The final else branch of createConflictExpression throws when expressionMap.onUpdate is set but the driver supports neither 'on-conflict-do-update' (Postgres/SQLite family) nor 'on-duplicate-key-update' (MySQL/MariaDB). This means .orUpdate() was called on a driver like Oracle, SAP HANA, or MongoDB that has no upsert primitive TypeORM can emit.

Source

Thrown at packages/@n8n/typeorm/src/query-builder/InsertQueryBuilder.ts:476

			} else if (this.connection.driver.supportedUpsertTypes.includes('on-duplicate-key-update')) {
				if (this.expressionMap.onUpdate) {
					const { overwrite, columns } = this.expressionMap.onUpdate;

					if (Array.isArray(overwrite)) {
						query += ' ON DUPLICATE KEY UPDATE ';
						query += overwrite
							.map((column) => `${this.escape(column)} = VALUES(${this.escape(column)})`)
							.join(', ');
						query += ' ';
					} else if (Array.isArray(columns)) {
						query += ' ON DUPLICATE KEY UPDATE ';
						query += columns.map((column) => `${this.escape(column)} = :${column}`).join(', ');
						query += ' ';
					}
				}
			} else {
				if (this.expressionMap.onUpdate) {
					throw new TypeORMError(`onUpdate is not supported by the current database driver`);
				}
			}
		}

		// add RETURNING expression
		if (returningExpression && DriverUtils.isPostgresFamily(this.connection.driver)) {
			query += ` RETURNING ${returningExpression}`;
		}

		return query;
	}

	/**
	 * Gets list of columns where values must be inserted to.
	 */
	protected getInsertedColumns(): ColumnMetadata[] {
		if (!this.expressionMap.mainAlias!.hasMetadata) return [];

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Check dataSource.driver.supportedUpsertTypes before calling .orUpdate(); fall back to a manual select-then-insert/update.
  2. Use repository.save() or an upsert() method that handles driver differences internally.
  3. Switch to a driver that supports upserts (Postgres, MySQL, SQLite) if upsert is essential.
  4. Set upsertType: 'primary-key' only if your driver supports the primary-key conflict path.

Example fix

// before
await dataSource.createQueryBuilder()
  .insert().into(User).values(payload)
  .orUpdate({ conflict: ['email'], overwrite: ['name'] }) // throws on Oracle
  .execute();

// after
const supportsUpsert = dataSource.driver.supportedUpsertTypes.length > 0;
if (supportsUpsert) {
  await dataSource.createQueryBuilder().insert().into(User).values(payload)
    .orUpdate({ conflict: ['email'], overwrite: ['name'] }).execute();
} else {
  await dataSource.getRepository(User).upsert(payload, ['email']);
}
Defensive patterns

Strategy: validation

Validate before calling

function driverSupportsUpsert(ds: DataSource): boolean {
  return ds.driver.supportedUpsertTypes.length > 0;
}
if (!driverSupportsUpsert(dataSource)) { /* manual select-then-insert/update */ }

Type guard

function driverSupportsUpsert(driver: import('../driver/Driver').Driver): boolean {
  return driver.supportedUpsertTypes.length > 0;
}

Try / catch

try {
  await qb.insert().into(E).values(v).orUpdate(opts).execute();
} catch (e) {
  if (e instanceof TypeORMError && /onUpdate is not supported/.test(e.message)) { /* fallback */ }
  throw e;
}

Prevention

When it happens

Trigger: Calling .orUpdate(...) on an InsertQueryBuilder whose connection.driver.supportedUpsertTypes contains neither upsert type. Also triggered when upsertType is not 'primary-key' (which bypasses this block) and the driver lacks any upsert support.

Common situations: Running upsert code on Oracle or SAP HANA. CI against SQLite where 'on-conflict-do-update' IS supported but the driver config doesn't advertise it. Using MongoDB driver with relational upsert API.

Related errors


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