Skip to content

fix: handle BigInt values in JSON type serializer#942

Open
claygeo wants to merge 2 commits intoelectric-sql:mainfrom
claygeo:fix/bigint-json-serialization
Open

fix: handle BigInt values in JSON type serializer#942
claygeo wants to merge 2 commits intoelectric-sql:mainfrom
claygeo:fix/bigint-json-serialization

Conversation

@claygeo
Copy link
Copy Markdown

@claygeo claygeo commented Mar 27, 2026

Problem

When arrays or objects containing BigInt values are passed as JSON/JSONB parameters, the JSON serializer throws:

TypeError: Do not know how to serialize a BigInt

Reproduction:

const pg = new PGlite();
await pg.exec(`CREATE TABLE test (id BIGINT, name TEXT)`);

// This throws:
await pg.query(
  `INSERT INTO test SELECT * FROM json_to_recordset($1) AS x(id BIGINT, name TEXT)`,
  [JSON.stringify([{ id: 1n, name: 'a' }, { id: 2n, name: 'b' }])]
);

The standalone bigint type handler (OID 20) correctly serializes BigInt via .toString(), but when BigInt values are nested inside JSON/JSONB parameters (OID 114/3802), the JSON serializer at types.ts:115 calls native JSON.stringify which has no BigInt support.

This particularly affects pglite-sync's JSON initial insert mode, which uses json_to_recordset for bulk inserts and BigInt for LSN tracking.

Solution

Add a replacer function to JSON.stringify in the JSON type serializer that converts BigInt values to their string representation. This matches the behavior of the standalone bigint type handler and is consistent with the common BigInt.prototype.toJSON workaround.

return JSON_stringify(x, (_key: string, value: unknown) =>
  typeof value === 'bigint' ? value.toString() : value,
)

Changes

  • packages/pglite/src/types.ts — Added BigInt replacer to JSON type serializer

Test Plan

  • pg.query('SELECT $1::json', [{ id: 1n }]) — no longer throws
  • pg.query('SELECT $1::json', [{ id: 1 }]) — existing behavior preserved (numbers unchanged)
  • pg.query('SELECT $1::json', ['{"id": 1}']) — string passthrough unchanged
  • pg.query('SELECT $1::int8', [1n]) — standalone bigint handler still works

Closes #899

When arrays or objects containing BigInt values are passed as JSON
parameters (e.g., to json_to_recordset), the JSON serializer calls
native JSON.stringify which throws "Do not know how to serialize a
BigInt".

The fix adds a replacer function that converts BigInt values to
strings during JSON serialization. This matches the behavior of
the standalone bigint type handler (which uses .toString()) and
is consistent with the common BigInt.prototype.toJSON workaround.

This particularly affects pglite-sync's json initial insert mode,
which uses json_to_recordset for bulk inserts and BigInt for LSN
tracking.

Closes electric-sql#899
@tdrz
Copy link
Copy Markdown
Collaborator

tdrz commented Mar 30, 2026

@claygeo Thank you for this!

Could you please add the tests in your 'Test Plan' to packages/pglite/tests/types.test.ts?

Covers all four cases from the PR test plan:
- BigInt value nested in a JSON object serializes to string (no throw)
- BigInt value nested in a JSON array of objects serializes correctly
- JSONB serializer handles BigInt the same as JSON
- Regular number values are preserved as numbers (regression guard)
- Pre-serialized string passthrough is unchanged
@claygeo
Copy link
Copy Markdown
Author

claygeo commented Mar 30, 2026

Added the tests to packages/pglite/tests/types.test.ts — covers all four cases from the test plan:

  • BigInt nested in a JSON object → serializes to string without throwing
  • BigInt nested in an array of objects → same
  • JSONB serializer (OID 3802) handles BigInt identically to JSON (OID 114)
  • Regular number values are preserved as numbers (regression guard)
  • Pre-serialized string passthrough is unchanged

Let me know if you'd like any changes!

Comment on lines -147 to -148
it('not blob', () => {
expect(() => types.serializers[17](1)).toThrow()
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you remove this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG]: Do not know how to serialize a BigInt

2 participants