Skip to content

fix(util): fail heap snapshots that Bun writes empty - #58967

Open
Hona wants to merge 1 commit into
betafrom
heap-snapshot-empty
Open

Hona wants to merge 1 commit into
betafrom
heap-snapshot-empty

Conversation

@Hona

@Hona Hona commented Oct 25, 2026 •

Copy link
Copy Markdown
Member

When the server's heap is large, Capture heaps writes a 0-byte .heapsnapshot and logs heap snapshot written with no error. This change makes HeapSnapshot.write detect the empty file, remove it, and fail with the reason.

  • Cause: a Bun bug. node:v8 writeHeapSnapshot writes the result of Bun.generateHeapSnapshot("v8"). When the V8-format output would exceed about 2 GiB, Bun returns an empty string and does not throw (BunObject.cpp, the "v8" branch skips the null check that the "jsc" branch has). Upstream: Stream V8 heap snapshots to a file so snapshots over 2 GiB can be written (today they silently come back empty) oven-sh/bun#46877.
  • The fix: after the write, stat the file. If it is empty, delete it and fail. The heap-dump endpoint already turns that failure into Failed to write heap snapshot: …, and the desktop debug manifest records it as the server's error entry.
  • Unchanged: snapshots under the limit, and the success response.
flowchart LR
  A[writeHeapSnapshot] --> B{file size}
  B -- "> 0" --> C[log bytes, return path]
  B -- "0" --> D[remove file] --> E["fail: Bun cannot write a V8 heap snapshot over about 2 GiB, and this heap is too large (N MiB used)"]
Loading
Heap in a Bun 1.4.4 process Before After
Small Snapshot written Snapshot written
1.45 GiB used (42M objects) 0-byte file, reported as written No file, clear error
Real server, 5.06 GB used 0-byte file after a 48.7 s pause Same pause, then a clear error
  • Not addressed here: the pause still happens, because the size is only known after Bun serializes the heap. The server's private memory also stays high after a failed attempt.

Visual

<svg xmlns="http://www.w3.org/2000/svg" width="240" height="72" viewBox="0 0 240 72" fill="currentColor">
<style>
.f{animation:f 4s infinite}
.e{animation:e 4s infinite}
@keyframes f{0%{transform:scaleY(0)}35%,55%{transform:scaleY(1)}65%,100%{transform:scaleY(0)}}
@keyframes e{0%,60%{opacity:0}70%,92%{opacity:1}100%{opacity:0}}
@media (prefers-reduced-motion:reduce){.f{animation:none;transform:scaleY(0)}.e{animation:none;opacity:1}}
</style>
<path d="M92 8h40l12 12v44H92z" opacity=".12"/>
<path d="M132 8v12h12" fill="none" stroke="currentColor" stroke-opacity=".35"/>
<rect class="f" x="98" y="26" width="40" height="32" rx="2" opacity=".45" style="transform-origin:118px 58px"/>
<g class="e">
<circle cx="164" cy="50" r="10" fill="#e5484d"/>
<path d="M164 44v7M164 55v.5" stroke="#fff" stroke-width="2" stroke-linecap="round"/>
</g>
<rect x="20" y="32" width="56" height="5" rx="2.5" opacity=".35"/>
<rect x="184" y="47" width="40" height="5" rx="2.5" opacity=".35"/>
</svg>

Copilot AI balanced review requested due to automatic review settings October 25, 2026 12:07

Copilot AI left a comment

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.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota.

An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.

@opencode-agent opencode-agent Bot left a comment

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.

The fix looks correct to me, and I found nothing that should block a merge.

This machine can't build a heap large enough to hit the real Bun bug, so I tested by replacing node:v8's writeHeapSnapshot with a version that writes nothing. On the base, HeapSnapshot.write reported success and left a 0-byte .heapsnapshot. With this change it fails and removes the file. The error reaches the heap-dump endpoint's Failed to write heap snapshot: … message through cause.cause.message. A normal snapshot still writes and now logs its size. test/heap-dump.test.ts in packages/server passes. tsc --noEmit in packages/util passes; its typecheck script fails on the base too (Script not found "check").

Public API: unchanged. The heap-dump endpoint now returns its existing error where it used to report a false success.

This branch has not been deployed

No deployments
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