{"id":"e920ea8cc2c48222","repo":"drizzle-team/drizzle-orm","slug":"you-cannot-use-both-where-and-targetwhere-set","errorCode":null,"errorMessage":"You cannot use both \"where\" and \"targetWhere\"/\"setWhere\" at the same time - \"where\" is deprecated, use \"targetWhere\" or \"setWhere\" instead.","messagePattern":"You cannot use both \"where\" and \"targetWhere\"/\"setWhere\" at the same time - \"where\" is deprecated, use \"targetWhere\" or \"setWhere\" instead\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"drizzle-orm/src/pg-core/query-builders/insert.ts","lineNumber":373,"sourceCode":"\t *     target: cars.id,\n\t *     set: { brand: 'Porsche' }\n\t *   });\n\t *\n\t * // Upsert with 'where' clause\n\t * await db.insert(cars)\n\t *   .values({ id: 1, brand: 'BMW' })\n\t *   .onConflictDoUpdate({\n\t *     target: cars.id,\n\t *     set: { brand: 'newBMW' },\n\t *     targetWhere: sql`${cars.createdAt} > '2023-01-01'::date`,\n\t *   });\n\t * ```\n\t */\n\tonConflictDoUpdate(\n\t\tconfig: PgInsertOnConflictDoUpdateConfig<this>,\n\t): PgInsertWithout<this, TDynamic, 'onConflictDoNothing' | 'onConflictDoUpdate'> {\n\t\tif (config.where && (config.targetWhere || config.setWhere)) {\n\t\t\tthrow new Error(\n\t\t\t\t'You cannot use both \"where\" and \"targetWhere\"/\"setWhere\" at the same time - \"where\" is deprecated, use \"targetWhere\" or \"setWhere\" instead.',\n\t\t\t);\n\t\t}\n\t\tconst whereSql = config.where ? sql` where ${config.where}` : undefined;\n\t\tconst targetWhereSql = config.targetWhere ? sql` where ${config.targetWhere}` : undefined;\n\t\tconst setWhereSql = config.setWhere ? sql` where ${config.setWhere}` : undefined;\n\t\tconst setSql = this.dialect.buildUpdateSet(this.config.table, mapUpdateSet(this.config.table, config.set));\n\t\tlet targetColumn = '';\n\t\ttargetColumn = Array.isArray(config.target)\n\t\t\t? config.target.map((it) => this.dialect.escapeName(this.dialect.casing.getColumnCasing(it))).join(',')\n\t\t\t: this.dialect.escapeName(this.dialect.casing.getColumnCasing(config.target));\n\t\tthis.config.onConflict = sql`(${\n\t\t\tsql.raw(targetColumn)\n\t\t})${targetWhereSql} do update set ${setSql}${whereSql}${setWhereSql}`;\n\t\treturn this as any;\n\t}\n\n\t/** @internal */","sourceCodeStart":355,"sourceCodeEnd":391,"githubUrl":"https://github.com/drizzle-team/drizzle-orm/blob/b7862528fd8fc39bc2653a6c18dad7c1f4e68d10/drizzle-orm/src/pg-core/query-builders/insert.ts#L355-L391","documentation":"PgInsert.onConflictDoUpdate (insert.ts:372) forbids combining the legacy `where` option with the newer `targetWhere`/`setWhere`. The `where` key was deprecated because it was ambiguous; `targetWhere` qualifies the conflict target (the partial index predicate region) and `setWhere` qualifies the UPDATE. Mixing them would produce ambiguous SQL, so the library rejects the combination explicitly.","triggerScenarios":"Calling onConflictDoUpdate({ target, set, where, targetWhere }) or onConflictDoUpdate({ target, set, where, setWhere }) in the same config object — typically during a migration from the old `where` API to the new split predicates.","commonSituations":"Upgrading drizzle-orm and copy-pasting a partial-index upsert example that uses targetWhere while still holding an old `where`; refactoring an upsert to support a partial unique index; merging code that inconsistently uses the two APIs.","solutions":["Remove the deprecated `where` and use `targetWhere` (to filter the conflict target) and/or `setWhere` (to filter the UPDATE).","If `where` was meant to gate the UPDATE, move it to `setWhere`.","If `where` was meant to qualify the index target, move it to `targetWhere`.","Audit all onConflictDoUpdate call sites after upgrading drizzle-orm to remove residual `where` keys."],"exampleFix":"// before\ndb.insert(t).values(r).onConflictDoUpdate({\n  target: t.id, set: { v: 'x' },\n  where: sql`t.v > 0`, targetWhere: sql`t.tenant = 1`, // conflict\n});\n\n// after\ndb.insert(t).values(r).onConflictDoUpdate({\n  target: t.id, set: { v: 'x' },\n  targetWhere: sql`t.tenant = 1`, setWhere: sql`t.v > 0`,\n});","handlingStrategy":"validation","validationCode":"function normalizeConflict(cfg: any) {\n  if (cfg.where && (cfg.targetWhere || cfg.setWhere)) {\n    // migrate legacy where into setWhere (UPDATE predicate) by default\n    cfg.setWhere = cfg.setWhere ?? cfg.where;\n    delete cfg.where;\n  }\n  return cfg;\n}\nawait db.insert(t).values(r).onConflictDoUpdate(normalizeConflict(conflictConfig));","typeGuard":"function isLegacyWhere(cfg: unknown): cfg is { where: unknown } {\n  return typeof cfg === 'object' && cfg !== null && 'where' in cfg;\n}","tryCatchPattern":null,"preventionTips":["Migrate all onConflictDoUpdate call sites off `where` when upgrading.","Keep `targetWhere` (index predicate) and `setWhere` (UPDATE predicate) distinctly named.","Search the codebase for `where:` inside onConflict configs after upgrades."],"tags":["insert","upsert","on-conflict","migration","validation"],"analyzedSha":"b7862528fd8fc39bc2653a6c18dad7c1f4e68d10","analyzedAt":"2026-08-03T18:11:14.318Z","schemaVersion":2}