Skip to content

fix: catch plugin event handler errors and provide logger to plugins#12929

Open
wilfoa wants to merge 1 commit intoanomalyco:devfrom
wilfoa:fix/plugin-event-error-handling
Open

fix: catch plugin event handler errors and provide logger to plugins#12929
wilfoa wants to merge 1 commit intoanomalyco:devfrom
wilfoa:fix/plugin-event-error-handling

Conversation

@wilfoa
Copy link

@wilfoa wilfoa commented Feb 10, 2026

Fixes #12931

Summary

  • Wrap plugin event handler calls in try-catch with await so that both sync throws and async rejections are caught instead of crashing the TUI or going uncaught.
  • Provide a log property on PluginInput so plugins can log to OpenCode's log file instead of writing to stderr (which corrupts the TUI display).

Problem

Plugin event handlers registered via Bus.subscribeAll were called without error handling:

  1. A sync throw in a handler would propagate up and crash the bus subscriber.
  2. An async rejection (returned rejected promise) was completely uncaught since the handler wasn't awaited.
  3. Plugins had no way to log errors except console.error(), which writes to stderr and corrupts the TUI output.

This was observed in practice when a Telegram notification plugin's API call failed — the error message was rendered directly into the TUI chat window.

Changes

packages/opencode/src/plugin/index.ts

  • Create a scoped logger via Log.create({ service: "plugin.user" })
  • Pass log (with info, warn, error, debug methods) to plugins via PluginInput
  • Wrap each hook["event"]?.() call in try-catch with await, logging errors via the logger

packages/plugin/src/index.ts

  • Add PluginLogger type with info, warn, error, debug methods
  • Add log: PluginLogger to the PluginInput interface

packages/opencode/test/plugin/event-error-handling.test.ts

  • 5 integration tests verifying:
    1. Sync throw doesn't crash the bus
    2. Async rejection doesn't crash the bus
    3. Throwing plugin doesn't prevent other plugins from receiving events
    4. Errors are logged via Log system, not stderr
    5. log property is provided with all expected methods

All 908 tests pass. Typecheck passes across all 12 packages.

Plugin event handlers that throw errors or call console.error() can
corrupt the TUI display since stderr output appears inline in the
terminal.

This change:
1. Wraps plugin event handler calls in try-catch so unhandled exceptions
   are logged to the log file instead of crashing or corrupting the TUI.
2. Adds a `log` property to PluginInput, giving plugins a proper way to
   log messages to OpenCode's log file instead of using console.error().
3. Adds `await` to the event handler call so errors are properly caught.
4. Adds tests proving:
   - Throwing plugins don't crash the bus event loop
   - Async rejections are caught
   - A throwing plugin doesn't prevent other plugins from receiving events
   - Errors are logged via Log system, not printed to stderr
   - The log property is available to plugins with all expected methods
@github-actions
Copy link
Contributor

Thanks for your contribution!

This PR doesn't have a linked issue. All PRs must reference an existing issue.

Please:

  1. Open an issue describing the bug/feature (if one doesn't exist)
  2. Add Fixes #<number> or Closes #<number> to this PR description

See CONTRIBUTING.md for details.

@github-actions
Copy link
Contributor

The following comment was made by an LLM, it may be inaccurate:

No duplicate PRs found

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Plugin event handler errors corrupt TUI display

1 participant