drizzle-team/drizzle-orm · error · Error

You cannot use both "where" and "targetWhere"/"setWhere" at

Error message

You cannot use both "where" and "targetWhere"/"setWhere" at the same time - "where" is deprecated, use "targetWhere" or "setWhere" instead.

What it means

Thrown by SQLiteInsertBase.onConflictDoUpdate (insert.ts:350) when the config object supplies both the deprecated 'where' key and at least one of the newer 'targetWhere'/'setWhere' keys. Drizzle migrated the ON CONFLICT WHERE clause into two distinct filters (targetWhere for the conflict target, setWhere for the UPDATE) and made 'where' deprecated; mixing them is ambiguous and rejected.

Source

Thrown at drizzle-orm/src/sqlite-core/query-builders/insert.ts:350

	 *   .values({ id: 1, brand: 'BMW' })
	 *   .onConflictDoUpdate({
	 *     target: cars.id,
	 *     set: { brand: 'Porsche' }
	 *   });
	 *
	 * // Upsert with 'where' clause
	 * await db.insert(cars)
	 *   .values({ id: 1, brand: 'BMW' })
	 *   .onConflictDoUpdate({
	 *     target: cars.id,
	 *     set: { brand: 'newBMW' },
	 *     where: sql`${cars.createdAt} > '2023-01-01'::date`,
	 *   });
	 * ```
	 */
	onConflictDoUpdate(config: SQLiteInsertOnConflictDoUpdateConfig<this>): this {
		if (config.where && (config.targetWhere || config.setWhere)) {
			throw new Error(
				'You cannot use both "where" and "targetWhere"/"setWhere" at the same time - "where" is deprecated, use "targetWhere" or "setWhere" instead.',
			);
		}

		if (!this.config.onConflict) this.config.onConflict = [];

		const whereSql = config.where ? sql` where ${config.where}` : undefined;
		const targetWhereSql = config.targetWhere ? sql` where ${config.targetWhere}` : undefined;
		const setWhereSql = config.setWhere ? sql` where ${config.setWhere}` : undefined;
		const targetSql = Array.isArray(config.target) ? sql`${config.target}` : sql`${[config.target]}`;
		const setSql = this.dialect.buildUpdateSet(this.config.table, mapUpdateSet(this.config.table, config.set));
		this.config.onConflict.push(
			sql` on conflict ${targetSql}${targetWhereSql} do update set ${setSql}${whereSql}${setWhereSql}`,
		);
		return this;
	}

	/** @internal */

View on GitHub (pinned to b7862528fd)

Solutions

  1. Remove the deprecated 'where' key and use 'targetWhere' (filter the conflict target) and/or 'setWhere' (filter the update) instead.
  2. If you only need one WHERE clause, pick the semantically correct new key and drop 'where'.
  3. Grep the codebase for onConflictDoUpdate and remove every lingering 'where' after a version upgrade.

Example fix

// before
.onConflictDoUpdate({
  target: users.id,
  set: { name: 'x' },
  where: sql`...`,       // deprecated
  targetWhere: sql`...`, // new — combining throws
});

// after
.onConflictDoUpdate({
  target: users.id,
  set: { name: 'x' },
  targetWhere: sql`...`, // filter the conflict target
  setWhere: sql`...`,    // filter the update
});
Defensive patterns

Strategy: validation

Validate before calling

function onConflictConfig(cfg) {
  if (cfg.where && (cfg.targetWhere || cfg.setWhere)) {
    throw new Error('Remove deprecated "where"; use targetWhere/setWhere');
  }
  return cfg;
}

Prevention

When it happens

Trigger: Calling .onConflictDoUpdate({ target, set, where, targetWhere }) or { where, setWhere } — any combination that includes where alongside targetWhere or setWhere.

Common situations: Upgrading drizzle and keeping old 'where' while adding the new keys; copy-pasting an example that used the old API next to new-style config; partial migration of upsert calls.

Related errors


AI-assisted analysis of drizzle-team/drizzle-orm@b7862528fd (2026-08-03). Data as JSON: /data/errors/c2e56689d64540b0.json. Report an issue: GitHub.