Repository navigation
tui: leaks ~21MB .so per launch into /tmp; fills tmpfs and breaks TUI startup #42700
Description
Activity
github-actions commented
on Aug 15, 2026 on Aug 15, 2026 – with GitHub ActionsContributorMore actionsThis issue might be related to an existing open issue that covers the same root cause. Please check:
- v2 cli: headless commands load OpenTUI and leak native temp files #37671: v2 cli: headless commands load OpenTUI and leak native temp files — same underlying bun
bun:ffiextraction pattern, same symptom of uniquely-named.sofiles accumulating in/tmpuntil the filesystem fills up.
Your report is distinct in that it focuses on the interactive TUI itself leaking on every launch (rather than headless commands), so it may warrant tracking separately if the fix scopes differ.
- v2 cli: headless commands load OpenTUI and leak native temp files #37671: v2 cli: headless commands load OpenTUI and leak native temp files — same underlying bun
Update: the unbounded native-library temp-file growth described here is fixed in OpenCode V2.
As of V2 build
0.0.0-dev-17643, the compiled CLI uses Bun 1.4.0-canary.1 (681a49bee). That runtime includes oven-sh/bun#29587, which replaces the unique temporary.so/.dylib/.nodeextraction on every load with a deterministic, content-hashed path reused across calls, Workers, processes, and restarts. The V2 build provenance is workflow run 32216069554.This bounds extraction to one reusable file per embedded native module and user instead of allowing unbounded disk growth. It does not mean the temp directory will contain zero native files, and upgrading does not remove files leaked by older builds; those stale randomly named files can be cleaned up after all older OpenCode processes have stopped.
Interestingly I couldn't update opencode2 via curl as I had this issue with the .so files causing the crash.
When I ran:
curl -fsSL https://opencode.ai/v2/install | bashI got:
curl: (23) Failure writing output to destination, passed 1369 returned 1367Once I ran
find . -name "/tmp/*.so" -type f -deleteThen curl worked fine. Also curl seems to get version
0.0.0-dev-17639from curl so assume 643 isn't updated yet?Interestingly I couldn't update opencode2 via curl as I had this issue with the .so files causing the crash.
When I ran:
curl -fsSL https://opencode.ai/v2/install | bashI got:
curl: (23) Failure writing output to destination, passed 1369 returned 1367Once I ran
find . -name "/tmp/*.so" -type f -deleteThen curl worked fine. Also curl seems to get version
0.0.0-dev-17639from curl so assume 643 isn't updated yet?you can force curl to install the beta release channel using
curl -fsSL https://opencode.ai/v2/install|bash -s -- --version 0.0.0-beta-17639you run
npm view @opencode-ai/cli dist-tags --jsonto view the different tags[ { "tui-v2": "0.0.0-tui-v2-202606261840", "latest": "1.18.18", "next": "0.0.0-beta-17498", "beta": "0.0.0-beta-17639", "dev": "0.0.0-dev-17706" } ]Occurrence report — additional diagnostic evidence (opencode 1.18.23, stable channel)
Confirming this also reproduces on the stable channel (
1.18.23, Linux x86_64), plus one new data point: extraction happens not only per launch, but also during active session activity while the TUI stays open.Measurements from this machine:
- Accumulation rate during active use: ~5 new
.soblobs/min tied to session/turn bursts; 57 files (~634 MB) piled up within a single working day on a tmpfs-backed/tmp— i.e. it consumed RAM directly. A previous heavy-use day reached ~2,000 files / ~11 GB. - Every extracted copy is byte-identical: all sampled files share the same size (13,745,312 bytes) and md5 — it is the same embedded
libopentui.sore-extracted over and over (SONAME confirmed viareadelf -d; Zig-built ELF with debug info). - No process keeps an fd open after creation (
lsofon the files returns nothing, and a deleted-fd scan comes up empty). The library appears to be mapped once and the temp file abandoned, so deleting while the TUI is running was safe here as well. - Creation stops entirely while the session is idle: a 70-second idle watch produced zero new files; creation resumed immediately with session activity. This suggests per-turn/per-burst re-initialization rather than a single per-process extraction.
Workarounds currently in place (both effective so far):
- Launching with
TMPDIRpointed at a disk-backed directory → leak lands on disk instead of tmpfs RAM. - Hourly cron purge:
find /tmp -maxdepth 1 -regextype posix-extended -regex '.*/\.[0-9a-f]{16}-00000000\.so' -mmin +90 -delete
Happy to test a candidate fix (stable-name reuse or exit-time cleanup) if useful.
- Accumulation rate during active use: ~5 new
macOS (arm64) variant: continuous
.dylibleak during a session, ~1.6 GB/hourSame root mechanism as this report (bunfs embedded-library extraction into the temp dir with no cleanup), but on macOS the artifact extension is
.dyliband the leak is continuous while a session runs, not just once per launch. Worth fixing here since it fills internal SSDs on Macs quickly.Environment
- opencode
1.18.23, macOS 26.6.2 (build 25G83), arm64 - Bundled Bun runtime
v24.18.0
Observed behavior
- Files matching
$TMPDIR/.5bff*-00000000.dylib(also saw.5bfe*,.b9de*,.b9df*prefixes over time) — Mach-O 64-bit dynamically linked shared library, arm64, ~3.6 MB each. - Leak is continuous during active usage, not one file per launch: measured 9,316 files / 33 GB accumulated in ~21 hours ≈ 1.6 GB/hour (~one file every 8 s), with
lsofshowing the runningopencodeprocess holding them open. - On a 256 GB-class internal SSD this drove the disk to ~50% full within a day; a prior occurrence reached ~71 GB before manual cleanup.
Reproduction
- Run opencode TUI, keep an active session going for a few hours.
find "$TMPDIR" -maxdepth 1 -name '.5bff*-*.dylib' | wc -l→ grows hundreds of files/hour.lsof +D "$TMPDIR"→ owned by theopencodeprocess.
Expected behavior
Extracted runtime libraries are either reused across launches / stable-named or removed when no longer needed. The temp dir should not grow unboundedly during a single session.
Workaround (safe on macOS)
Deleting an open file on macOS is safe — space is reclaimed when the holding process exits and Bun re-JITs on demand:
find "$TMPDIR" -maxdepth 1 -type f -name '.*-*.dylib' -deleteI installed a 30-minute purge agent to contain this; that is mitigation, not a fix.
Notes
- This is the macOS sibling of the Linux
.soleaks (tui: leaks ~21MB .so per launch into /tmp; fills tmpfs and breaks TUI startup #42700, Runaway /tmp .589*-00000000.so artifacts can exhaust disk during long-running usage #16996): same bunfs$bunfs/root/lib…extraction pattern, extension differs by platform. - No plugins or config involved; reproduces with default setup.
- opencode
Another data point for this, with a failure mode I don't see covered in the existing reports: on a distro that puts a per-user quota on
/tmp, this bug bites at 80% of the tmpfs, not 100%, and it takes down unrelated programs rather than opencode itself.Environment
- opencode:
1.18.25(standalone binary,~/.opencode/bin/opencode, 184 MB) - OS: Fedora Linux 44 (KDE Plasma), kernel
7.1.10-200.fc44.x86_64 - systemd:
259 (259.8-1.fc44) - Terminal:
xterm-256color
What accumulated
1010 byte-identical copies of the extracted library, ~6.2 GB total:
$ ls -1 /tmp/.*-00000000.so | wc -l 1010 $ du -shc /tmp/.*-00000000.so | tail -1 6,2G total $ md5sum /tmp/.9adb5ebfeaedff8f-00000000.so /tmp/.9adb5ef9ffe6ed87-00000000.so d08bd9a52225cacba076f60cca5a697e ... d08bd9a52225cacba076f60cca5a697e ... # identical $ objdump -p /tmp/.9adb5ebfeaedff8f-00000000.so | grep SONAME SONAME libopentui.soEach file is 13,745,312 bytes (13.10 MiB) — smaller than the ~21 MB reported in the issue body, so the size tracks the opentui/bun version. Timestamps spanned 19:48–22:59 on a single day: ~1010 launches accumulated in about three hours of normal use.
Why the quota makes this worse
Fedora 44 ships systemd's stock
tmp.mount, which enables tmpfs user quota:Options=mode=1777,strictatime,nosuid,nodev,size=50%,nr_inodes=1m,x-systemd.graceful-option=usrquotaThe default per-user limit is 80% of the filesystem. So on a 7.8 GB
/tmpthe ceiling is 6360 MB, and the leak hit it whiledfstill showed 20% free:$ df -h /tmp tmpfs 7,8G 6,3G 1,6G 80% /tmp $ quota -s -u <user> Filesystem space quota limit grace tmpfs 6359M 6360M 6360MThe part that cost the most time to diagnose
opencode itself kept working. What broke was everything else that writes to
/tmp, and it broke silently. Writes returnedEDQUOT, which surfaced as shells that exit 1 with empty stdout and empty stderr — the failing component never got to report anything:$ echo hello # exit 1, no output $ true # exit 1, no outputtruereturning 1 is what finally gave it away: the shell was dying before executing anything, because its wrapper couldn't create a temp file. Any tool that stages work through/tmpshows the same shape — it just stops, with no error to search for. Tracking it back to opencode took reading/proc/mountsto spotusrquota, thenobjdump -pon one of the files to getSONAME: libopentui.so.Worth noting for the fix discussion:
usrquotaon/tmpis stock systemd ≥ 256 behaviour, not a Fedora patch, so this "fails early and blames the wrong process" mode will get more common as distros pick up newer systemd.Confirming the files are orphans
None of the 1010 copies were mapped by any live process, so they are pure garbage rather than in-use libraries:
$ lsof /tmp/.*-00000000.so | wc -l 0 $ ls -l /proc/*/map_files/ 2>/dev/null | grep -c '00000000.so' 0Deleting them reclaimed the full 6.2 GB and restored
/tmpto 1% used, with no restart needed.Workaround
Since
rlines intmpfiles.ddon't accept an age field andsystemd-tmpfiles --cleandoesn't process them, atmpfiles.drule alone can't express "delete files matching this glob older than N minutes". A systemd user timer works without root:# ~/.local/bin/clean-opentui-tmp.sh find /tmp -maxdepth 1 -type f -user "$(id -u)" -name '.*-00000000.so' -mmin +60 -print0 | while IFS= read -r -d '' f; do lsof -- "$f" >/dev/null 2>&1 || rm -f -- "$f" done
driven hourly by
OnUnitActiveSec=1h. The-mmin +60andlsofguards are belt-and-braces — deleting a mapped.sois safe on Linux, since the inode survives until unmapped — but they keep the purge from racing a launch that has just extracted its copy.- opencode:
Genuinely impressed that an open source project this big can be leaking gigabytes of data per day and it goes unfixed. Pretty embarrassing tbh. Also caused me to lose several hours of work so fuck you guys.
Reacted by Scott Williams and Alexandre Pinon- added a commit that references this issue
on Sep 25, 2026 this was due to a bug in bun itself, opencode v2 uses bun 1.4+ instead which does not have the same issue.
Summary
The TUI leaks a ~21 MB
.sofile into the temp directory on every launch and never cleans it up. After many launches the temp filesystem fills up, and the TUI then fails to start with an OpenTUI library load error.Environment
Reproduction
opencode2(TUI) in a terminal, exit it. Repeat the launch several times (each launch generates a fresh extraction).ls -la /tmp | grep '\.so$'— each launch adds a file like.39dbfbfdbf6bfbff-00000000.so(~21 MB, random hash prefix per launch). 2,338 files / ~13 GB accumulated over days of normal use on this machine.Expected Behavior
The extracted library file is either reused across launches (stable name / extracted once) or removed when the TUI exits. The temp directory should not grow unboundedly.
Actual Behavior
Every TUI launch extracts a fresh hashed
.so(~21 MB) into$TMPDIR(default/tmp) and leaves it there. On this machine the files accumulated to ~13 GB, filling the tmpfs and causing the startup failure above. Clearing/tmp/.[0-9a-f]*-*.sorestores normal operation (2,338 files deleted, 13 GB reclaimed). Other processes doing large tmpfs writes (Gradle/Kotlin daemons, build tools) make the failure arrive sooner.Additional Context
rm /tmp/.[0-9a-f]*-*.so(safe — the running TUI keeps the loaded library mapped; a daily cron purge was installed to keep the box usable).bunfs), so this likely affects any bun-compiled binary that extracts libraries into the temp dir without cleanup.