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)

Open
#6,038 1 comment 0 reactions 0 assignees View on GitHub
bug
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.