anomalyco / anomalyco/opencode
TUI SIGILL (ud2) in OpenTUI drawTextBuffer when compositor scale jumps to 4
@kommander is already working on this.
Since Aug 12, 2026.
- Dominant language
- TypeScript
- Stars
- 209k
- Forks
- 27.5k
- PR merge metrics
- PR metrics pending
Description
Summary
An idle OpenCode TUI aborts with SIGILL (ud2) the instant the compositor scales the monitor up to 4. This has happened twice, weeks apart, on two OpenCode versions, at the same instruction pointer and on the same second as the scale-to-4 event.
This is not a missing-CPU-feature SIGILL. The faulting instruction is a deliberate ud2 abort in the bundled Bun runtime, reached from OpenTUI's text-buffer draw path.
Same abort site as #41483 (opencode+0x2407064 / libopentui.so+0x1d061d), but a different trigger: a healthy local foot session that had already been running for ~56 minutes, not a partial capability handshake at startup.
What happened
- Started
opencode --autoin foot on Hyprland (18:38). - Worked in a session, then left the TUI idle (last session write 18:56:40).
- Scaled the external display DP-1 from 3.13 → 4.
- Kernel recorded the abort on that same second:
Aug 12 19:34:41 traps: opencode[3769384] trap invalid opcode ip:2607064
The process dumped core (si_code: ILL_ILLOPN). No OOM, 37 GiB free.
Reproduction
Reliable on this machine whenever OpenCode's TUI is open and the monitor is scaled to 4.
- Hyprland + foot, OpenCode TUI running (
opencode --autois enough; session can be idle). - External display: Apple Pro Display XDR,
6016x3384@60. - Scale DP-1 up through 2 → ~3.13 → 4.
- OpenCode dies immediately with
SIGILL.
Logical resolution at those scales:
| scale | logical size |
|---|---|
| 2 | 3008×1692 |
| 3.13 | 1920×1080 |
| 4 | 1504×846 |
Going 2 → 3.13 did not kill it. The abort is on the step to 4.
Two hits, same abort, same trigger
| when | version | command | scale event (same second) |
|---|---|---|---|
| 2026-08-04 19:27:23 CEST | 1.18.11 | opencode --auto |
DP-1 3.20 → 4 |
| 2026-08-12 19:34:41 CEST | 1.18.16 | opencode --auto |
DP-1 3.13 → 4 |
Both cores have identical offsets:
#0 opencode + 0x2407064 ; ud2
#1 opencode + 0x2405266
#2 opencode + 0x32dd8bf ; napi_internal_suppress_crash_on_abort_if_desired
#3 opencode + 0x44e35ad
#4 libc.so.6 + 0x3e6f0 ; __restore_rt
#5 libopentui.so + 0x1d061d
That is the same #0/#5 pair reported in #41483.
Symbolized OpenTUI frame
libopentui.so is still on disk (/tmp/.9adb5cbffaf2ed8f-00000000.so, not stripped, has DWARF). addr2line on frame #5:
buffer.OptimizedBuffer.trySetTransparentTextCellFast
packages/core/src/zig/buffer.zig:896
called from:
OptimizedBuffer.drawTextBufferInternal buffer.zig:1659
OptimizedBuffer.drawTextBuffer buffer.zig:1274
lib.bufferDrawTextBufferView lib.zig:2521
The instruction at that offset is a cell-buffer load inside the fast path (cmpl $0xff, (%rsi,%rcx,4)), not a SIMD op.
Faulting bytes in the main binary:
260705f: call 0x2634e80 ; noreturn abort helper
2607064: ud2 ; <- RIP
2607066: int3 int3 int3 ...
Classic Zig/Bun "noreturn returned" / panic abort, which the kernel reports as trap invalid opcode.
Inference (not proven)
Scale 3.13 → 4 shrinks the logical viewport by ~22% and delivers a SIGWINCH / TIOCSWINSZ to foot. OpenTUI then redraws. trySetTransparentTextCellFast indexes self.buffer.char[index] with no bounds check; OptimizedBuffer.resize reallocs those arrays. A draw that still holds an index computed against the pre-resize width/height would trip a Zig safety panic, which becomes this ud2.
I have not single-stepped the panic reason (no panic string in the journal). The timestamp match + the symbolized draw path is the evidence.
Ruled out
- OOM / resource exhaustion
- AVX / "baseline binary on old CPU" (Intel Core Ultra X7 358H, avx2+; the opcode is
ud2, not EVEX) - A crash in the herdr OpenCode plugin — it is installed, but it is not on the crashing stack
--autoitself (that is just how the agent is launched; the abort is in the renderer)
Environment
- opencode 1.18.16 (previous hit: 1.18.11), installed via mise
- Bun v1.3.14 (Linux x64 baseline), bundled
- OpenTUI native
libopentui.soextracted to/tmp/.9adb5cbffaf2ed8f-00000000.so - OS Arch Linux, kernel
7.1.5-arch1-1-ptl, glibc 2.44 - compositor Hyprland 0.56.2
- terminal foot 1.27.0, JetBrainsMono Nerd Font 9
- display Apple Pro Display XDR
DP-16016×3384@60 - CPU Intel Core Ultra X7 358H
Expected
A compositor scale change (or any SIGWINCH / resize) should reflow the TUI. It should not abort the process.
Workaround
Do not scale the monitor to 4 while OpenCode is open, or close OpenCode first. Session data in ~/.local/share/opencode/opencode.db survived; the crash was during an idle redraw.
Related
- #41483 — identical
ud2/libopentui+0x1d061d, trigger is a partial capability handshake at startup - #38199 — TUI crash on extreme shrink (~2×1); Bun segfault, different stack
- anomalyco/opentui#971 — OpenTUI
bufferDrawBoxpanic on grapheme / clip
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.