Skip to content

fix(executor): make step and workflow JSONB writes BigInt-safe#1472

Open
joelorzet wants to merge 1 commit into
stagingfrom
fix/KEEP-720-bigint-jsonb-serialization
Open

fix(executor): make step and workflow JSONB writes BigInt-safe#1472
joelorzet wants to merge 1 commit into
stagingfrom
fix/KEEP-720-bigint-jsonb-serialization

Conversation

@joelorzet
Copy link
Copy Markdown

Step outputs that contain a BigInt (gas amounts, block numbers, token values from web3 steps) crashed when drizzle-orm serialized them to a JSONB column: PgJsonb.mapToDriverValue runs JSON.stringify, which throws Do not know how to serialize a BigInt. The redacted output column was already protected, but the raw output_raw path (added later) and the step input column had no guard, so any step returning a raw BigInt anywhere crashed at the persistence boundary.

Fix

  • Add a shared toJsonSafe helper (lib/utils/json-safe.ts) that recursively normalizes BigInt, Uint8Array/Buffer, Map, Set, Date and circular refs to JSON-safe values.
  • Apply it to the input, output, output_raw and workflow-level output writes in lib/workflow/executor/logging.ts, so no non-serializable value can reach a JSONB column regardless of which step produced it.
  • Harden batch-read-contract: when a call has no ABI outputs it returned the raw ethers Result (carrying BigInts) instead of serializing it.

Verification

Reproduced the exact crash and confirmed the fix against a real workflow_execution_logs.output_raw write (the PgJsonb.mapToDriverValue site): a raw-BigInt payload throws pre-fix and round-trips to strings post-fix. Unit tests cover toJsonSafe (BigInt, nested structures, Date, Buffer, Map/Set, circular refs) and the existing batch-read-contract suite passes.

Step outputs that contain a BigInt (gas amounts, block numbers, token
values from web3 steps) crashed when drizzle-orm serialized them to a
JSONB column: PgJsonb.mapToDriverValue runs JSON.stringify, which throws
on BigInt. The redacted output column was already protected, but the
raw output_raw path (and step input) had no guard.

Add a shared toJsonSafe helper that recursively normalizes BigInt,
Uint8Array/Buffer, Map, Set, Date and circular refs to JSON-safe values,
and apply it to the input, output, output_raw and workflow output writes
at the persistence boundary so no non-serializable value can reach JSONB.

Also harden batch-read-contract: when a call has no ABI outputs it
returned the raw ethers Result (with BigInts) instead of serializing it.
@joelorzet joelorzet requested review from a team, OleksandrUA, eskp and suisuss and removed request for a team June 5, 2026 15:27
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.

1 participant