drizzle-team / drizzle-team/drizzle-orm
[BUG]: db.batch() shifts column values for duplicate column names on Cloudflare D1 (a single query maps them correctly)
- Dominant language
- TypeScript
- Stars
- 35.8k
- Forks
- 1.6k
- Avg merge
- 2d 7h
- Merged PRs (30d)
- 4
Description
### Report hasn't been filed before.
- [x] I have verified that the bug I'm about to report hasn't been filed before.
### What version of `drizzle-orm` are you using?
0.45.2
### What version of `drizzle-kit` are you using?
0.31.10
### Other packages
wrangler@4.x, @cloudflare/workers-types@5
### Describe the Bug
### Summary
When a query selects two columns that share the same underlying column name, running it as a single query maps the selection correctly, but running **the exact same query through `db.batch()` shifts the column values by one**, leaving the last field `undefined`.
- Database engine: **Cloudflare D1**
- Driver: **`drizzle-orm/d1`**
- Runtime: reproduced locally on **Node.js 24** using wrangler's `getPlatformProxy()` to access a local D1 instance.
### Minimal reproduction
Full runnable repo: **https://github.com/stinbox/drizzle-d1-batch-bug-repro** (`pnpm install && pnpm repro`)
Schema — both tables have a primary key named `id`:
```ts
export const users = sqliteTable("users", {
id: integer().primaryKey(),
name: text().notNull(),
});
export const posts = sqliteTable("posts", {
id: integer().primaryKey(),
userId: integer()
.notNull()
.references(() => users.id),
title: text().notNull(),
});
```
The query selects `users.id` and `posts.id` (both named `id`) plus `posts.title`:
```ts
const buildQuery = () =>
db
.select({
userId: users.id, // expected: 1
postId: posts.id, // expected: 100
postTitle: posts.title, // expected: "Hello D1"
})
.from(posts)
.innerJoin(users, eq(users.id, posts.userId));
const [singleQueryRow] = await buildQuery(); // single query
const [batchResult] = await db.batch([buildQuery()]); // same query via db.batch()
const batchRow = batchResult[0];
console.log("single query:", singleQueryRow);
console.log("db.batch() :", batchRow);
```
### Undesired behavior (actual)
```
single query: { userId: 1, postId: 100, postTitle: 'Hello D1' }
db.batch() : { userId: 100, postId: 'Hello D1', postTitle: undefined }
```
With `db.batch()` the values are shifted by one column and the last field becomes `undefined`. The single-query execution of the identical query is correct.
### Desired result
`db.batch()` should return the same rows as running the query on its own:
```
{ userId: 1, postId: 100, postTitle: 'Hello D1' }
```
### Steps to reproduce
1. `git clone https://github.com/stinbox/drizzle-d1-batch-bug-repro`
2. `pnpm install`
3. `pnpm repro`
The script is idempotent and exits with code `1` when the bug reproduces, printing both results.
### Relation to existing issues
This is the same kind of column shift as:
- **#555** (`Broken shifted columns with leftJoin and same column name (on D1)`) — about single queries; appears fixed for single queries (the single-query case in this repro is correct).
- **#838** (`Shifting column values when querying through junction table`) — also about single queries; closed with the reasoning that duplicate column names would clash in raw SQL too, so it's not an ORM issue.
The difference here: **the identical query maps correctly as a single query but shifts only when run through `db.batch()`.** Because the single-query path already returns the correct mapping, the "it would clash in raw SQL anyway" reasoning from #838 does not apply to this case — it is an inconsistency between single-query and
`db.batch()` execution.
Contributor guide
Research direction
Clone the linked drizzle-d1-batch-bug-repro repository, run `pnpm install && pnpm repro`, and compare the single-query and `db.batch()` results shown in the issue. Trace the D1 batch mapping entry point and verify that duplicate `id` selections produce the same `{ userId, postId, postTitle }` values in both execution paths.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- nodejs, sqlite, typescript
- Domain
- databases
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 70/100