Skip to content

TUI crashes at startup (Bun SIGILL in drainMicrotasks, libopentui) when the terminal answers the capability handshake only partially #41483

Description

@IamKaleb21

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:

  1. Answering only OSC 10/11 → still crashed (5/5)
  2. 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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions