Skip to content

[BUG]: Drizzle inserts/updates JSONB fields as strings (postgres) #5287

@imdoroshenko

Description

@imdoroshenko

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?

v1.0.0-beta.15

What version of drizzle-kit are you using?

v1.0.0-beta.15

Other packages

I use Bun.SQL

Describe the Bug

What is the undesired behavior?

When inserting/updating, Drizzle saves JSONB fields as strings.

What are the steps to reproduce it?

Do update/insert:

const value = []
await db
  .update(my_table)
  .set({ value })
  .where(eq(my_table.id, id))

Check actual data (notice quotes around the value):

postgres=# select value from my_table where id = '...';
 value 
-------
 "[]"
(1 row)

What is the desired result?

Expected result in the DB:

postgres=# select value from my_table where id = '...';
 value 
-------
 []
(1 row)

Workaround

const value = []
await db
  .update(my_table)
  .set(sql.raw(`'${JSON.stringify(value)}'::jsonb`))
  .where(eq(my_table.id, id))

Related issue

#4701

UPDATE

Bug is reproducible in beta-15. I was able narrow down the issue to bun:sql.

I generated a small test that reproduces the issue.

https://github.com/imdoroshenko/drizzle-test

clone the repo, and then run:

bun install
bun run start

Output:

 bun run start
$ docker start drizzle-test-pg 2>/dev/null || docker run -d --name drizzle-test-pg -e POSTGRES_PASSWORD=postgres -p 5555:5432 postgres:17-alpine > /dev/null && bun run wait-for-pg && bun run index.ts; docker stop drizzle-test-pg > /dev/null
drizzle-test-pg
$ until docker exec drizzle-test-pg pg_isready -U postgres -q 2>/dev/null; do sleep 0.5; done
Query: DROP TABLE IF EXISTS test
Query: CREATE TABLE test (id SERIAL PRIMARY KEY, col1 JSONB)

--- INSERT empty array ---
Query: insert into "test" ("id", "col1") values (default, $1) -- params: ["[]"]

--- INSERT object ---
Query: insert into "test" ("id", "col1") values (default, $1) -- params: ["{\"key\":\"value\",\"nested\":{\"a\":1}}"]

--- INSERT array of objects ---
Query: insert into "test" ("id", "col1") values (default, $1) -- params: ["[{\"name\":\"item1\",\"active\":true}]"]

--- UPDATE id=1 with empty array ---
Query: update "test" set "col1" = $1 where "test"."id" = $2 -- params: ["[]", 1]

--- Checking stored values via raw SQL ---
  id=1  col1="[]"  js_type=string  pg_type=jsonb  ← BUG: stored as string
  id=2  col1="{\"key\":\"value\",\"nested\":{\"a\":1}}"  js_type=string  pg_type=jsonb  ← BUG: stored as string
  id=3  col1="[{\"name\":\"item1\",\"active\":true}]"  js_type=string  pg_type=jsonb  ← BUG: stored as string

✗ BUG CONFIRMED: JSONB values are double-serialized

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions