Skip to content

tui: attention sound corrupts the terminal when no audio device is available #55302

Closed as duplicate

Description

@AlexeyShirshov

Description

With attention.sound: true, the TUI's built-in audio engine tries to open an ALSA PCM on every attention event. On a machine with no audio devices (WSL2), alsa-lib writes its diagnostics to the TUI process's stderr — the same terminal the TUI draws to — so they land inside the alternate screen and corrupt the rendered frame. The TUI only repaints part of the screen afterwards, so the garbled frame stays until a full redraw/restart.

Expected: no sound (or one logged warning). Audio-backend diagnostics must never be written to the terminal the TUI owns.

Plugins

superpowers@git+https://github.com/obra/superpowers.git, btw-context, roslyn, windows-notify (local server plugins); git-status, sidebar-plugins (CLI plugins). None of them touch audio — the failing path is built in.

OpenCode version

opencode v2.0.28 (latest channel, binary at ~/.opencode/bin/opencode).

Steps to reproduce

Host without audio devices:

ls /dev/snd                    # only "timer", no pcm*
cat /proc/asound/cards         # No such file or directory
ls /run/user/$(id -u)/pulse    # empty — no PulseAudio server
command -v paplay pactl aplay ffplay   # none installed
  1. Enable sounds in ~/.config/opencode/cli.json:

    "attention": { "enabled": true, "sound": true, "volume": 0.4, "sound_pack": "opencode.default" }
  2. Start the TUI and trigger any attention event — a permission request is enough.

  3. The frame is corrupted by the alsa-lib output below.

The same 8 lines are produced by any process that touches ALSA on this host, which shows the noise comes from the audio backend and not from rendering:

python3 -c "import ctypes; a=ctypes.CDLL('libasound.so.2'); h=ctypes.c_void_p(); print('rc=', a.snd_pcm_open(ctypes.byref(h), b'default', 0, 0))"
ALSA lib confmisc.c:855:(parse_card) cannot find card '0'
ALSA lib conf.c:5182:(_snd_config_evaluate) function snd_func_card_inum returned error: No such file or directory
ALSA lib confmisc.c:422:(snd_func_concat) error evaluating strings
ALSA lib conf.c:5182:(_snd_config_evaluate) function snd_func_concat returned error: No such file or directory
ALSA lib confmisc.c:1334:(snd_func_refer) error evaluating name
ALSA lib conf.c:5182:(_snd_config_evaluate) function snd_func_refer returned error: No such file or directory
ALSA lib conf.c:5705:(snd_config_expand) Evaluate error: No such file or directory
ALSA lib pcm.c:2664:(snd_pcm_open_noupdate) Unknown PCM default
rc= -2

Reproducible every time (100%) here. Only the TUI client is affected; ~/.local/share/opencode/log/opencode.log contains nothing about audio.

Screenshot and/or share link

Screenshot of the corrupted frame available; can attach it to this issue on request. The exact text that corrupts the screen is in the code block above.

Operating System

Ubuntu 22.04 on WSL2 (6.18.33.2-microsoft-standard-WSL2), Windows 11 host.

Terminal

Windows Terminal attached to WSL2 (WT_SESSION set); TERM=xterm-256color, TERM_PROGRAM and COLORTERM unset.

Additional notes

  • In v2.0.28 the client bundle ships a miniaudio-based audio engine (loadSoundFile/play) with bundled mp3 packs mapped per event (default/done = bip-bop-01, question = bip-bop-03, permission = staplebops-06, error = nope-03, subagent_done = yup-01), and it dlopens libasound.so.2 / libpulse.so.0. PulseAudio is tried before ALSA, so a desktop with a working PulseAudio server never hits this — which is probably why it is easy to miss.
  • Workarounds: attention.sound: false removes it. opencode 2>/tmp/opencode.err also keeps the noise off the screen (sound still cannot play). attention.notifications: true is unaffected — only the audio path corrupts the screen.
  • Suggestion: swallow/redirect the audio backend's stderr (or skip audio init when no output device exists and log it once) instead of letting it write to the TUI's terminal.

Activity

  1. AlexeyShirshov commented on Oct 14, 2026

    @AlexeyShirshov
    Author

    Service context, as requested in the troubleshooting guide:

    • opencode service status → http://127.0.0.1:49374
    • opencode api get /api/info → {"version":"2.0.28","pid":3241981,"urls":["http://127.0.0.1:49374"]}

    So the shared service is healthy and reachable; the corruption happens entirely in the TUI client, and no audio-related line appears in ~/.local/share/opencode/log/opencode.log (grepping for alsa|audio|sound returns nothing from the client).

  2. opencode-agent commented on Oct 14, 2026

    @opencode-agent
    Contributor

    I'm still triaging this issue; I'll answer here when that's done.

  3. opencode-agent commented on Oct 14, 2026

    @opencode-agent
    Contributor

    Thanks for the very thorough report, including the clean ALSA repro and the workarounds. I think this is a duplicate of #41763. On Linux hosts with no audio device, the TUI's audio backend makes alsa-lib write its diagnostics to stderr when an attention sound plays, and they end up drawn over the TUI.

    Possible duplicates and related issues, ordered by likelihood:

    Until that's resolved, the workarounds you found (attention.sound: false, or redirecting stderr) are the way to go. Your WSL2/PulseAudio details would be useful on #41763.

    The bot will close this issue as a duplicate in 1 day unless you reply explaining how your problem is different.

  4. opencode-agent commented on Oct 14, 2026

    @opencode-agent
    Contributor

    Thanks for checking the service. A healthy service and nothing about audio in opencode.log is what #41763 would lead us to expect. The TUI client starts the audio backend itself, and alsa-lib writes straight to the TUI's terminal (stderr), not to OpenCode's log. That's why only the client is affected and the server log stays clean.

    So this still looks like a duplicate of #41763. Open PR #51854 there would skip audio setup when no playback device exists. Until then, attention.sound: false or opencode 2>/tmp/opencode.err avoids the corruption. Your WSL2 details would also be useful on #41763.

    If your setup differs from #41763 in a way I've missed, please reply here before the bot closes this as a duplicate.

  5. AlexeyShirshov commented on Oct 14, 2026

    @AlexeyShirshov
    Author

    Closing as a duplicate. This is already tracked by #41763 and, for the WSL2 variant, #52793 — and I should have searched for existing reports before filing this one. I have moved the extra reproduction details to the tracking issues:

    The fix path is #51854 (skip audio init when no playback device exists). Workarounds until then: attention.sound: false, or opencode 2>/tmp/opencode.err.

  6. opencode-agent commented on Oct 15, 2026

    @opencode-agent
    Contributor

    Closing this as a duplicate of #41763, since there's been no reply in the past day. That issue covers the same problem: on Linux hosts with no audio device, the TUI's audio backend makes alsa-lib write its errors to the terminal (stderr) when an attention sound plays, and they corrupt the screen. Please follow #41763 for updates; your WSL2 details would be useful there. Open PR #51854 would skip audio setup when no playback device exists. Until then, attention.sound: false or opencode 2>/tmp/opencode.err avoids the corruption. Thanks again for the detailed report!

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions