Skip to content

fix(sqlite3): handle Bun structured-clone surfacing null as zero-length ArrayBuffer#250

Open
subsetpark wants to merge 1 commit into
vercel-labs:mainfrom
flowglad:upstream-pr/sqlite3-bun-coerce-buffer
Open

fix(sqlite3): handle Bun structured-clone surfacing null as zero-length ArrayBuffer#250
subsetpark wants to merge 1 commit into
vercel-labs:mainfrom
flowglad:upstream-pr/sqlite3-bun-coerce-buffer

Conversation

@subsetpark

Copy link
Copy Markdown
Contributor

Summary

Bun's worker_threads structured-clone has regressed across versions — most visibly in the build shipped in Trigger.dev's runtime container — and surfaces a host-side null dbBuffer as a zero-length ArrayBuffer inside the worker thread.

The current call site treats any truthy data.dbBuffer as a database image:

if (data.dbBuffer) {
  db = new SQL.Database(data.dbBuffer);
} else {
  db = new SQL.Database();
}

An empty ArrayBuffer is truthy in JS, so the buggy clone slips past the guard and reaches sql.js — which rejects bare ArrayBuffer (it wants Uint8Array) with:

Expected ArrayBuffer for the first argument

Net effect: every :memory: sqlite3 invocation throws under affected Bun builds.

Change

Introduce coerceDbBuffer(raw: unknown): Uint8Array | null in the worker and route the buffer through it:

const buf = coerceDbBuffer(data.dbBuffer);
db = buf ? new SQL.Database(buf) : new SQL.Database();

Behavior:

  • Uint8Array (and Buffer, which extends Uint8Array) — returned as-is
  • non-empty ArrayBuffer — wrapped in a Uint8Array
  • null, undefined, zero-length buffers — collapsed to null, so executeQuery falls back to new SQL.Database() (a fresh in-memory db, which is what the host meant for :memory:)

No Node-side behavior change. Fixes :memory: invocations under affected Bun builds.

Test plan

  • pnpm --filter just-bash typecheck — clean
  • pnpm --filter just-bash exec vitest run src/commands/sqlite3/157/157 pass (6 new unit tests pin each branch of coerceDbBuffer, including the zero-length ArrayBuffer regression that previously broke)
  • pnpm --filter just-bash check:worker-sync — clean (worker.js rebuilds deterministically; the .js is gitignored so it isn't shipped in this diff)

Background

We've been carrying this in flowglad/just-bash since Trigger.dev's container shipped a Bun version that exhibits the regression. The fix is orthogonal to the dot-command preprocessor work in #249; opening as a separate PR for cleaner review.

🤖 Generated with Claude Code

…th ArrayBuffer

Bun's worker_threads structured-clone has regressed across versions
(notably the build shipped in Trigger.dev's container) and surfaces a
host-side `null` dbBuffer as a zero-length ArrayBuffer inside the
worker. The prior `if (data.dbBuffer)` guard treated that as truthy,
so `new SQL.Database(arrayBuffer)` ran with a bare ArrayBuffer —
which sql.js rejects with "Expected ArrayBuffer for the first
argument" (it wants Uint8Array, not bare ArrayBuffer).

Route the buffer through a `coerceDbBuffer` helper that:

- returns a Uint8Array as-is (covers Buffer too, which extends
  Uint8Array),
- wraps a non-empty ArrayBuffer in a Uint8Array,
- and returns null for null / undefined / zero-length buffers —
  letting executeQuery fall back to `new SQL.Database()` (fresh
  in-memory db), which matches the host's intent for :memory:
  databases.

No behavior change under Node; fixes :memory: invocations under
affected Bun builds. Six unit tests pin each branch.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@subsetpark subsetpark requested a review from cramforce as a code owner May 19, 2026 17:38
@vercel

vercel Bot commented May 19, 2026

Copy link
Copy Markdown

@subsetpark is attempting to deploy a commit to the Vercel Labs Team on Vercel.

A member of the Team first needs to authorize it.

* matching the host's intent for :memory: databases.
*/
export function coerceDbBuffer(raw: unknown): Uint8Array | null {
if (raw instanceof Uint8Array) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Explain how this change is not a security risk

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

What's the vector you've got in mind?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It's a sensitive area of code going from simple to complicated, so it is worth asking

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.

2 participants