Plugin event handler errors corrupt TUI display #8954

Open
opened 2026-02-16 18:11:15 -05:00 by yindo · 0 comments
Owner

Originally created by @wilfoa on GitHub (Feb 10, 2026).

Originally assigned to: @rekram1-node on GitHub.

Description

Plugin event handlers registered via the plugin system can corrupt the TUI display when they throw errors or write to stderr.

Steps to Reproduce

  1. Create a plugin with an event handler that either:
    • Throws an error (sync or async)
    • Calls console.error() to log failures
  2. Trigger the event (e.g., session.idle)
  3. Observe the error output rendered directly into the TUI chat window

Expected Behavior

  • Plugin event handler errors should be caught and logged to the OpenCode log file
  • Plugins should have access to a proper logging mechanism instead of relying on console.error()
  • A failing plugin should not prevent other plugins from receiving events

Actual Behavior

  • Sync throws propagate up and crash the bus subscriber
  • Async rejections are completely uncaught (handlers aren't awaited)
  • console.error() output goes to stderr, which corrupts the TUI display

Root Cause

In packages/opencode/src/plugin/index.ts, the Bus.subscribeAll callback calls hook["event"]?.() without:

  1. awaiting the result (so async errors are uncaught)
  2. Wrapping in try-catch (so sync errors propagate)

Additionally, plugins have no log property on PluginInput, so their only logging option is console.error() which writes to stderr.

Example occurance:

Image
Originally created by @wilfoa on GitHub (Feb 10, 2026). Originally assigned to: @rekram1-node on GitHub. ## Description Plugin `event` handlers registered via the plugin system can corrupt the TUI display when they throw errors or write to stderr. ## Steps to Reproduce 1. Create a plugin with an `event` handler that either: - Throws an error (sync or async) - Calls `console.error()` to log failures 2. Trigger the event (e.g., `session.idle`) 3. Observe the error output rendered directly into the TUI chat window ## Expected Behavior - Plugin event handler errors should be caught and logged to the OpenCode log file - Plugins should have access to a proper logging mechanism instead of relying on `console.error()` - A failing plugin should not prevent other plugins from receiving events ## Actual Behavior - Sync throws propagate up and crash the bus subscriber - Async rejections are completely uncaught (handlers aren't `await`ed) - `console.error()` output goes to stderr, which corrupts the TUI display ## Root Cause In `packages/opencode/src/plugin/index.ts`, the `Bus.subscribeAll` callback calls `hook["event"]?.()` without: 1. `await`ing the result (so async errors are uncaught) 2. Wrapping in try-catch (so sync errors propagate) Additionally, plugins have no `log` property on `PluginInput`, so their only logging option is `console.error()` which writes to stderr. Example occurance: <img width="1887" height="101" alt="Image" src="https://github.com/user-attachments/assets/cd0fc21e-fd27-4214-93c5-08b59ef5776e" />
yindo added the opentui label 2026-02-16 18:11:15 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: anomalyco/opencode#8954