Skip to content

[BUG]: SQLite onConflictDoNothing places the target WHERE after DO NOTHING (partial unique indexes) #6531

Open

Description

@CheHyeonYeong

Report hasn't been filed before.

  • I have verified that the bug I'm about to report hasn't been filed before.

What version of drizzle-orm are you using?

1.0.0-rc.4

What version of drizzle-kit are you using?

N/A

Other packages

Node.js 24 (node:sqlite)

Describe the Bug

onConflictDoNothing({ target, where }) in sqlite-core emits the where clause after do nothing, which SQLite rejects. This makes it impossible to target a partial unique index.

This is the same bug as #1628, which was fixed for Postgres in #2056, but the fix only touched pg-core/query-builders/insert.ts. The SQLite builder still has:

this.config.onConflict.push(sql` on conflict ${targetSql} do nothing${whereSql}`);

Reproduction

import { DatabaseSync } from 'node:sqlite';
import { isNull } from 'drizzle-orm';
import { drizzle } from 'drizzle-orm/node-sqlite';
import { integer, sqliteTable, text } from 'drizzle-orm/sqlite-core';

const users = sqliteTable('users', {
	id: integer().primaryKey(),
	email: text().notNull(),
	deletedAt: integer('deleted_at'),
});

const client = new DatabaseSync(':memory:');
client.exec(`
	CREATE TABLE users (id INTEGER PRIMARY KEY, email TEXT NOT NULL, deleted_at INTEGER);
	CREATE UNIQUE INDEX active_users_email_idx ON users (email) WHERE deleted_at IS NULL;
`);
const db = drizzle({ client });

const query = db
	.insert(users)
	.values({ email: 'a@example.com' })
	.onConflictDoNothing({ target: users.email, where: isNull(users.deletedAt) });

console.log(query.toSQL().sql);
query.run();

Actual

insert into "users" ("id", "email", "deleted_at") values (null, ?, null) on conflict ("users"."email") do nothing where ("users"."deleted_at" is null)
DrizzleQueryError: Failed query: ...
  cause: Error: near "where": syntax error

Expected

insert into "users" ("id", "email", "deleted_at") values (null, ?, null) on conflict ("users"."email") where ("users"."deleted_at" is null) do nothing

Per the [SQLite upsert syntax](https://www.sqlite.org/lang_upsert.html), the conflict target's WHERE must come before DO. Running the expected SQL directly with node:sqlite works as intended.

Workaround

onConflictDoUpdate({ target, targetWhere, set }) already emits the correct order, so a no-op set works in the meantime.

Suggested fix

- this.config.onConflict.push(sql` on conflict ${targetSql} do nothing${whereSql}`);
+ this.config.onConflict.push(sql` on conflict ${targetSql}${whereSql} do nothing`);

Happy to open a PR if that helps.

cc. @hyunbinseo

Activity

  1. changed the title [-][BUG]:[/-] [+][BUG]: SQLite onConflictDoNothing places the target WHERE after DO NOTHING (partial unique indexes)[/+] on Oct 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions