Summary
The TUI crashes deterministically at startup (Bun panic, SIGILL, inside JSC::VM::drainMicrotasks) when the terminal on the other end answers opencode's startup capability handshake only partially.
Reproduces 100% over the Moshi phone client. The same binary on the same machine starts fine in a local terminal, and — importantly — also starts fine over plain mosh with a locally attached mosh-client. So this is not "mosh" in general; it is terminal emulations that reply to some capability queries but not others.
Characterized over ~40 controlled runs.
Environment
- opencode 1.18.15 (also seen on 1.17.x)
- Bun 1.3.14 (bundled),
Linux x86_64_baseline [StandaloneExecutable]
- Arch Linux, kernel 6.18.42-1-lts, glibc 2.42
- Client: Moshi phone app (crash persists after updating both the phone app and
moshi-hook to 0.2.77)
Bun crash report
https://bun.report/1.3.14/Ba10d9b296m/Gz+339/D4664tE+uzP__suwxrCsuwxrCsuwxrCsuwxrCsuwxrCsuwxrCsuwxrCmsvprCi4wtpFusjtpF8s1muF4r338D__msvprCwpthhFA2k1/B4//o02C
Decoded: segfault at 0x7F5256A23FFC, recursive llint_op_call_ignore_result → JSC::MicrotaskQueue::drainImpl → JSC::VM::drainMicrotasks → Bun::jsFunctionDrainMicrotaskQueue (BunProcess.cpp:3806).
Coredump
SIGILL, command line opencode .:
#0 0x0000000002607064 (opencode + 0x2407064)
#1 0x0000000002605266 (opencode + 0x2405266)
#2 0x00000000034dd8bf (opencode + 0x32dd8bf)
#3 0x00000000046e35ad (opencode + 0x44e35ad)
#4 0x00007f4e5f83e6f0 (libc.so.6 + 0x3e6f0)
#5 0x00007f4e09c2061d (/tmp/.9adb59f9f3fcffdf-00000000.so + 0x1d061d) <-- libopentui
#6 0x000004305a263a93
#7 0x00007f4e12a0c038
#8 0x00000000025c60e7 (opencode + 0x23c60e7) <-- repeats x7, recursion
...
Frame #5 is the extracted libopentui.so (see #20043 for the /tmp extraction). The offset libopentui.so + 0x1d061d is identical across every crash.
Reproduction matrix
| Terminal on the other end |
Answers the handshake |
Result |
script, no terminal behind it |
nothing |
OK |
| real xterm |
everything |
OK (4/4) |
plain mosh-server + local mosh-client, sized pty |
— |
OK (2/2, verified today) |
mosh-server with no client attached |
nothing |
OK |
| herdr |
everything except OSC 10/11 |
CRASH |
| Moshi phone client |
partial |
CRASH (5/5) |
Nothing answered → clean fallback. Everything answered → works. An incomplete set → crash.
The handshake
Captured with a shim on the pty, opencode sends:
\x1b[?2031h \x1b]10;? \x1b]11;? \x1b[>0q \x1b[6n \x1bP+q4d73 \x1b[?1016$p \x1b[?2027$p
A real xterm replies with ]10;rgb:... and ]11;rgb:.... Moshi and herdr do not.
Two attempted fixes that did NOT work
A pty shim that intercepts the queries and answers them on the terminal's behalf:
- Answering only OSC 10/11 → still crashed (5/5)
- Answering all 7 captured queries and stripping them from the stream → still crashed (4/4)
So "missing replies" describes the symptom but is not the whole cause. Something about the partial interleaving appears to matter.
Ruled out (all still 100% crash)
TUI plugins, directory plugins, all plugins disabled, MCP servers, empty config, terminal width (tested 37 and 200 columns), and 13 combinations of OpenTUI env vars: OPENTUI_NOTIFICATIONS, OPENTUI_NOTIFICATION_PROTOCOL, OPENTUI_IMAGE_PROTOCOL, OPENTUI_GRAPHICS, OPENTUI_FORCE_EXPLICIT_WIDTH, OPENTUI_FORCE_WCWIDTH, OPENTUI_FORCE_NOZWJ, OTUI_NO_NATIVE_RENDER, OTUI_USE_ALTERNATE_SCREEN, OTUI_PALETTE_IDLE_TIMEOUT_MS, TERM=dumb, TERM=vt100, and faking TMUX/ZELLIJ.
A terminal multiplexer in the middle is not required: it crashes over the phone client with nothing in between.
Note on measuring
Count crashes with coredumpctl list | wc -l, not by reading the panel — the previous crash banner stays in the scrollback and produces false positives. Also start a fresh pane per attempt: a pane with a live opencode swallows the next command as keystrokes.
Related
Expected
A terminal that answers the capability handshake incompletely should fall back the same way a terminal that answers nothing does, instead of taking down the process.
Summary
The TUI crashes deterministically at startup (Bun panic,
SIGILL, insideJSC::VM::drainMicrotasks) when the terminal on the other end answers opencode's startup capability handshake only partially.Reproduces 100% over the Moshi phone client. The same binary on the same machine starts fine in a local terminal, and — importantly — also starts fine over plain mosh with a locally attached
mosh-client. So this is not "mosh" in general; it is terminal emulations that reply to some capability queries but not others.Characterized over ~40 controlled runs.
Environment
Linux x86_64_baseline [StandaloneExecutable]moshi-hookto 0.2.77)Bun crash report
https://bun.report/1.3.14/Ba10d9b296m/Gz+339/D4664tE+uzP__suwxrCsuwxrCsuwxrCsuwxrCsuwxrCsuwxrCsuwxrCmsvprCi4wtpFusjtpF8s1muF4r338D__msvprCwpthhFA2k1/B4//o02C
Decoded: segfault at
0x7F5256A23FFC, recursivellint_op_call_ignore_result→JSC::MicrotaskQueue::drainImpl→JSC::VM::drainMicrotasks→Bun::jsFunctionDrainMicrotaskQueue(BunProcess.cpp:3806).Coredump
SIGILL, command lineopencode .:Frame #5 is the extracted
libopentui.so(see #20043 for the/tmpextraction). The offsetlibopentui.so + 0x1d061dis identical across every crash.Reproduction matrix
script, no terminal behind itmosh-server+ localmosh-client, sized ptymosh-serverwith no client attachedNothing answered → clean fallback. Everything answered → works. An incomplete set → crash.
The handshake
Captured with a shim on the pty, opencode sends:
A real xterm replies with
]10;rgb:...and]11;rgb:.... Moshi and herdr do not.Two attempted fixes that did NOT work
A pty shim that intercepts the queries and answers them on the terminal's behalf:
So "missing replies" describes the symptom but is not the whole cause. Something about the partial interleaving appears to matter.
Ruled out (all still 100% crash)
TUI plugins, directory plugins, all plugins disabled, MCP servers, empty config, terminal width (tested 37 and 200 columns), and 13 combinations of OpenTUI env vars:
OPENTUI_NOTIFICATIONS,OPENTUI_NOTIFICATION_PROTOCOL,OPENTUI_IMAGE_PROTOCOL,OPENTUI_GRAPHICS,OPENTUI_FORCE_EXPLICIT_WIDTH,OPENTUI_FORCE_WCWIDTH,OPENTUI_FORCE_NOZWJ,OTUI_NO_NATIVE_RENDER,OTUI_USE_ALTERNATE_SCREEN,OTUI_PALETTE_IDLE_TIMEOUT_MS,TERM=dumb,TERM=vt100, and fakingTMUX/ZELLIJ.A terminal multiplexer in the middle is not required: it crashes over the phone client with nothing in between.
Note on measuring
Count crashes with
coredumpctl list | wc -l, not by reading the panel — the previous crash banner stays in the scrollback and produces false positives. Also start a fresh pane per attempt: a pane with a live opencode swallows the next command as keystrokes.Related
SIGILLon Linux x86_64, but a different trigger (crashes after running a while, not at startup).libopentui.soextraction into/tmp, which is the module in frame tweak: glob should be able to read certain hidden files/dirs #5.Expected
A terminal that answers the capability handshake incompletely should fall back the same way a terminal that answers nothing does, instead of taking down the process.