Repository navigation
Description
Summary
On WSL, when OpenCode's in-process native audio backend fails (e.g. ALSA cannot find a sound card on a stock WSLg setup), the library writes errors to stderr. OpenTUI does not capture stderr, so those bytes go to the same pty as the renderer and interleave with frame writes. Escape sequences get split and the terminal prints raw ANSI / garbled output. The corruption triggers exactly when a turn finishes (the attention "done" sound is played). It reproduces on any terminal and makes the TUI unreadable.
Environment
- opencode version: v2.0.22
- OS: Linux 6.6.87.2-microsoft-standard-WSL2 (Ubuntu 24.04.5 LTS), host Windows 11
- Terminal: Windows Terminal and Alacritty — both affected (also native
wsl), so it is not terminal-specific.TERM=xterm-256color,COLORTERMunset. - Shell: /bin/bash
- Install/channel: latest, native binary installed via the curl installer (
~/.opencode/bin/opencode, Bun-compiled ELF) - Active plugins:
@slkiser/opencode-quota@latest— ruled out (plugin was installed recently while the bug is weeks old, and the issue also occurs without it)
Reproduction
- In WSL, have
~/.config/opencode/cli.jsonwith"attention": { "sound": true }(playback enabled) and a system where WSLg's Pulse server exists (/mnt/wslg/PulseServer) but the ALSA→Pulse bridge is missing (libasound2-plugins/libpulse0not installed — the default on a fresh Ubuntu WSL image). - Run
opencodeand send any prompt; let a turn finish (so the attention "done" sound is played). - The ALSA library fails and prints errors to stderr; the TUI display becomes garbled and raw ANSI escape sequences are printed to the terminal.
Consistent (every turn), independent of the terminal and of content length.
Expected Behavior
An audio playback failure should not affect the TUI. The renderer output should stay intact, and native-library errors should not be written directly over the UI.
Actual Behavior
At the moment the turn ends, a burst of ALSA errors is written to stderr and lands on the same pty as the renderer. Escape sequences are split and the terminal shows raw ANSI / corrupted output.
Additional Context
I captured the full raw pty stream with script -q -c "opencode" out.raw (~267 KB) and analyzed it:
- All CSI/OSC/DCS sequences are well-formed: 0 literal SGR/CSI sequences (i.e. no escape printed as text) and 0 unterminated OSC/DCS.
- The only foreign bytes in the stream are 35 ALSA error lines in a single burst, immediately after the final
\x1b[?2026l(end of the synchronized-output block) of the first completed turn, at byte offset ~136155. - Renderer frames use mode 2026 (synchronized output) heavily; observed sync blocks up to ~22 KB.
Excerpt around the burst:
...\x1b[0m\x1b[65;6H\x1b[?25h\x1b[?2026l
ALSA lib confmisc.c:855:(parse_card) cannot find card '0'
ALSA lib conf.c:5208:(_snd_config_evaluate) function snd_func_concat returned error: No such file or directory
ALSA lib pcm.c:2721:(snd_pcm_open_noupdate) Unknown PCM default
ALSA lib confmisc.c:855:(parse_card) cannot find card '0'
... (35 lines total)
Hypothesized mechanism: the audio backend runs in-process and writes to stderr; per OpenTUI docs "stderr remains separate" (not captured), so it shares the controlling terminal. Frame writes can exceed PIPE_BUF and pty writes larger than that are not guaranteed to be atomic, so a stderr write can land in the middle of an escape sequence and split it — the terminal then renders the tail as literal text. This also matches the OpenTUI troubleshooting notes "Logs overwrite or corrupt the UI" and "Main-screen or split-footer rows remain damaged".
The binary references both libasound.so.2 and libpulse.so.0; on this system only libasound2 is installed, so playback goes through ALSA and fails ([ALSA] ... strings are embedded in the binary).
Workarounds that fully resolve the corruption:
- Install
libasound2-plugins+libpulse0and route ALSA to WSLg Pulse (~/.asoundrcwithpcm.!default { type pulse }), so audio works and no errors are emitted; or - Set
"attention": { "sound": false }in~/.config/opencode/cli.json.
Suggestions: capture/redirect stderr coming from native backends so it cannot write directly over the renderer, and/or suppress native library logging on the UI path.
Activity
github-actions commentedon Oct 2, 2026
This issue might be a duplicate of existing issues. Please check:
AlexeyShirshov commentedon Oct 14, 2026
Confirming from another WSL2 host (v2.0.28) — same trigger, plus a repro of the noise source without OpenCode
This matches my host exactly (WSL2 + attention sound + no audio device), and it is the closest match to what I hit, so I am adding my evidence here. My original report (#55302) is being closed as a duplicate of #41763 / this issue.
Environment: opencode
v2.0.28(latest channel,~/.opencode/bin/opencode), Ubuntu 22.04 on WSL2 (6.18.33.2-microsoft-standard-WSL2), Windows Terminal;TERM=xterm-256color,TERM_PROGRAMandCOLORTERMunset.Differences from the report above:
~/.local/share/opencode/log/opencode.loghas noalsa|audio|soundlines, andopencode service status(healthy athttp://127.0.0.1:49374) plusGET /api/infoare fine — consistent with the write happening in the TUI client's process, not the service.The burst is alsa-lib's, reproducible without OpenCode:
That confirms the bytes are emitted at the library level to stderr, not produced by the TUI renderer.
Audio device state:
Workarounds:
attention.sound: false(confirmed working), oropencode 2>/tmp/opencode.err(noise kept off-screen).Additional detail on v2.0.28: the client ships a miniaudio-based audio engine (
loadSoundFile/play) with bundled mp3 packs mapped per event, and dlopenslibasound.so.2/libpulse.so.0. PulseAudio is attempted before ALSA, so hosts with a working Pulse server do not reach the ALSA failure path — which is probably why this is easy to miss.Related: #41763 (tracking issue), #51854 (fix: skip audio init when no playback device exists).
neriousy commentedon Oct 20, 2026
Thanks for the detailed report and terminal capture! This is the same attention-sound problem tracked in #41763, where ALSA errors overwrite the TUI, including on WSL. Please subscribe or add a 👍 there, and feel free to add your terminal capture details to that issue.