You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Standalone executables leak a fresh TMPDIR copy of every dlopen'd embedded native library on each launch #40076
The temporary extraction of an embedded native library should be cleaned up after dlopen (or reused across launches), so running a compiled binary does not grow $TMPDIR.
What do you see instead?
Every launch extracts a fresh copy of the embedded library to $TMPDIR/.<hash>-<index>.so and never deletes it — not even on clean exit. After the two runs above:
$ ls -la /tmp/.59ee*
-rw-r--r-- 1 thomas thomas 15112 Aug 22 11:20 /tmp/.59ee776dfc9ebfd7-00000000.so
-rw-r--r-- 1 thomas thomas 15112 Aug 22 11:20 /tmp/.59ee776dfddbfeff-00000000.so
-rw-r--r-- 1 thomas thomas 15112 Aug 22 11:16 /tmp/.59ee77edf4bfbfbf-00000000.so
-rw-r--r-- 1 thomas thomas 15112 Aug 22 11:16 /tmp/.59ee77edf7b2bf97-00000000.so
One leaked file per process launch (the two 11:16 files are from earlier runs of the same binary).
Real-world impact
opencode ships a ~14 MB libopentui.so inside its compiled binary; it gets extracted to a fresh temp file on every launch and never unlinked. A user accumulated 44 orphaned copies (~533 MB), which filled /tmp completely — after which opencode failed to start at all with a misleading "Failed to open library ... No such file or directory" (the extraction write hits ENOSPC, so the path doesn't exist by the time dlopen runs).
Notes for a fix
Unlinking the temp file right after dlopen returns is safe on Linux/macOS: the inode survives for the existing mapping, and typical consumers (e.g. OpenTUI) never re-open the path. On Windows the unlink of a loaded DLL will fail, which can be ignored or deferred.
Alternatively, reuse one cached extraction per embedded library across launches (keyed by content hash) instead of extracting per launch.
The current failure mode when $TMPDIR is full also produces a confusing error: the reported bunfs path (/$bunfs/root/lib...so) looks like a packaging bug rather than ENOSPC.
This is fixed in Bun 1.4.0 by #29587. Each embedded library now extracts to one content-hashed file, $TMPDIR/.bun-{uid}-{contenthash}.{ext}. Every launch reuses that file instead of creating a new one.
Verified with your repro on 1.4.0: four launches of the compiled binary leave one file in $TMPDIR, not four. On 1.3.14 the same steps leave four.
Upgrade to Bun 1.4.0 or later. The opencode case stops accumulating copies once it ships with a fixed Bun. Existing orphaned .{hash}-{index}.so files from 1.3.x are safe to delete.
Duplicate of #29585, fixed by #29587 which shipped in Bun v1.4.0.
For the record, this repro confirms the bug on v1.3.14 (which predates the fix) — worth noting since binaries built with 1.3.x keep leaking even after users upgrade Bun itself, until the app ships a rebuild.
Activity
robobun commentedon Aug 22, 2026
This is fixed in Bun 1.4.0 by #29587. Each embedded library now extracts to one content-hashed file,
$TMPDIR/.bun-{uid}-{contenthash}.{ext}. Every launch reuses that file instead of creating a new one.Verified with your repro on 1.4.0: four launches of the compiled binary leave one file in
$TMPDIR, not four. On 1.3.14 the same steps leave four.Upgrade to Bun 1.4.0 or later. The opencode case stops accumulating copies once it ships with a fixed Bun. Existing orphaned
.{hash}-{index}.sofiles from 1.3.x are safe to delete.Archipel commentedon Aug 22, 2026
Duplicate of #29585, fixed by #29587 which shipped in Bun v1.4.0.
For the record, this repro confirms the bug on v1.3.14 (which predates the fix) — worth noting since binaries built with 1.3.x keep leaking even after users upgrade Bun itself, until the app ships a rebuild.
[NO-JIRA] Build releases with bun 1.4.0 to stop the 1.5 GB/day /tmp l…