Skip to content

Comments

feat(core): add plugin error hook for custom error routing#5192

Merged
Soulter merged 2 commits intoAstrBotDevs:masterfrom
Clhikari:feat/plugin-error-hook-5182
Feb 18, 2026
Merged

feat(core): add plugin error hook for custom error routing#5192
Soulter merged 2 commits intoAstrBotDevs:masterfrom
Clhikari:feat/plugin-error-hook-5182

Conversation

@Clhikari
Copy link
Contributor

@Clhikari Clhikari commented Feb 18, 2026

Closes #5182

Motivation / 改动动机

之前插件 handler 抛异常后,只能走框架默认报错回显,插件侧无法接管处理。这个在实际使用里有几个明显痛点:群里容易出现不友好的技术报错、插件作者无法把异常定向发到维护会话、不同插件各自处理也容易重复造轮子。
这次增加 OnPluginErrorEvent 的目标很直接:把“插件报错后的处理权”交还给插件作者。

带来的好处:

  • 方便插件开发者:可以统一接管异常(转发到指定群/私聊、脱敏后再提示、按需拦截默认回
    显)。
  • 方便插件开发者和管理员:拿到 plugin_namehandler_nametraceback_text,定位问题更快。
  • 方便普通用户:群聊里不再被默认报错文案打断,交互体验更干净。
  • 对现有生态友好:未注册该钩子的插件保持原行为,不是破坏性变更。

Modifications / 改动点

主要改动文件:

  • astrbot/core/star/star_handler.py
    新增事件类型 OnPluginErrorEvent

  • astrbot/core/star/register/star_handler.py
    新增 register_on_plugin_error 注册器。

  • astrbot/core/star/register/__init__.py
    导出 register_on_plugin_error

  • astrbot/api/event/filter/__init__.py
    导出 on_plugin_error 装饰器。

  • astrbot/core/pipeline/process_stage/method/star_request.py
    插件 handler 报错后触发 OnPluginErrorEvent,并传入:
    plugin_namehandler_nameerrortraceback_text
    若钩子侧调用 stop_event(),则不再发送默认报错回显。

  • astrbot/dashboard/routes/plugin.py
    WebUI 事件类型文案新增“插件报错时”。

  • This is NOT a breaking change. / 这不是一个破坏性变更。

Screenshots or Test Results / 运行截图或测试结果

验证目标:确认插件报错时会触发 OnPluginErrorEvent,且可通过 stop_event() 屏蔽默认报
错回显。

验证步骤:

  1. 在群聊发送 /hook_test_raise(该命令会主动抛出 RuntimeError)。
  2. 观察 Core 日志与聊天回显。

关键日志(节选):

[16:27:51.395] [ERRO] ... RuntimeError: hook_test_raise: expected failure
[16:27:51.397] [DBUG] ... hook(OnPluginErrorEvent) -> astrbot_plugin_office_assistant -
on_plugin_error
[16:27:53.471] [INFO] ... astrbot_plugin_office_assistant - on_plugin_error 终止了事件传
播。

结果说明:

  • OnPluginErrorEvent 已在插件异常后成功触发。
  • on_plugin_error 已执行并调用 stop_event()(日志显示“终止了事件传播”)。
  • 默认报错回显已被插件侧接管(聊天端不再出现框架默认 :( ... 报错文案)。

Checklist / 检查清单

  • 😊 如果 PR 中有新加入的功能,已经通过 Issue / 邮件等方式和作者讨论过。/ If there are new features added in the PR, I have discussed it with the authors through issues/emails, etc.
  • 👀 我的更改经过了良好的测试,并已在上方提供了“验证步骤”和“运行截图”。/ My changes have been well-tested, and "Verification Steps" and "Screenshots" have been provided above.
  • 🤓 我确保没有引入新依赖库,或者引入了新依赖库的同时将其添加到了 requirements.txtpyproject.toml 文件相应位置。/ I have ensured that no new dependencies are introduced, OR if new dependencies are introduced, they have been added to the appropriate locations in requirements.txt and pyproject.toml.
  • 😮 我的更改没有引入恶意代码。/ My changes do not introduce malicious code.

Summary by Sourcery

添加一个插件错误钩子事件,使插件能够拦截并自定义处理由插件处理器抛出的异常。

新增功能:

  • 引入 OnPluginErrorEvent 类型,用于表示插件处理器错误事件。
  • 新增 register_on_plugin_error 装饰器,并通过核心的 register 和 API filter 模块导出,以便插件能订阅插件错误事件。

增强内容:

  • 当插件处理器抛出异常时触发 OnPluginErrorEvent,允许钩子选择性地屏蔽框架的默认错误回复。
  • 更新仪表盘插件路由,在 Web UI 的事件类型列表中显示新的插件错误事件类型。
Original summary in English

Summary by Sourcery

Add a plugin error hook event to allow plugins to intercept and customize handling of exceptions thrown by plugin handlers.

New Features:

  • Introduce the OnPluginErrorEvent type to represent plugin handler error events.
  • Add a register_on_plugin_error decorator and export it through the core register and API filter modules so plugins can subscribe to plugin error events.

Enhancements:

  • Trigger the OnPluginErrorEvent when a plugin handler raises an exception, allowing hooks to optionally suppress the framework's default error reply.
  • Update the dashboard plugin routes to display the new plugin error event type in the Web UI event type list.

@dosubot dosubot bot added the size:M This PR changes 30-99 lines, ignoring generated files. label Feb 18, 2026
@dosubot
Copy link

dosubot bot commented Feb 18, 2026

Related Documentation

Checked 1 published document(s) in 1 knowledge base(s). No updates required.

How did I do? Any feedback?  Join Discord

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - 我发现了 1 个问题

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location> `astrbot/core/pipeline/process_stage/method/star_request.py:55-64` </location>
<code_context>
                 logger.error(f"Star {handler.handler_full_name} handle error: {e}")

-                if event.is_at_or_wake_command:
+                suppress_default_error_reply = await call_event_hook(
+                    event,
+                    EventType.OnPluginErrorEvent,
+                    md.name,
+                    handler.handler_name,
+                    e,
+                    traceback_text,
+                )
+
+                if not suppress_default_error_reply and event.is_at_or_wake_command:
                     ret = f":(\n\n在调用插件 {md.name} 的处理函数 {handler.handler_name} 时出现异常:{e}"
                     event.set_result(MessageEventResult().message(ret))
</code_context>

<issue_to_address>
**suggestion (bug_risk):** 将错误回复抑制逻辑与文档中描述的 `event.stop_event()` 行为对齐。

`register_on_plugin_error` 的文档字符串承诺 `event.stop_event()` 会抑制默认错误回复,但当前实现却依赖于 `call_event_hook` 的返回值(`suppress_default_error_reply`)。这会让行为绑定到一个辅助函数的返回约定,而不是事件本身的状态。

可以考虑在调用钩子之后检查事件状态:

```python
await call_event_hook(...)

if not event.is_stopped and event.is_at_or_wake_command:
    ...
```

或者,如果你打算继续使用返回值,请确保 `call_event_hook` 明确返回 `event.is_stopped`,并在文档中说明这一约定,以便与文档字符串保持一致。
</issue_to_address>

Sourcery 对开源项目免费——如果你觉得我们的评审有帮助,请考虑分享它们 ✨
帮我变得更有用!请对每条评论点 👍 或 👎,我会根据这些反馈改进你的代码评审体验。
Original comment in English

Hey - I've found 1 issue

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location> `astrbot/core/pipeline/process_stage/method/star_request.py:55-64` </location>
<code_context>
                 logger.error(f"Star {handler.handler_full_name} handle error: {e}")

-                if event.is_at_or_wake_command:
+                suppress_default_error_reply = await call_event_hook(
+                    event,
+                    EventType.OnPluginErrorEvent,
+                    md.name,
+                    handler.handler_name,
+                    e,
+                    traceback_text,
+                )
+
+                if not suppress_default_error_reply and event.is_at_or_wake_command:
                     ret = f":(\n\n在调用插件 {md.name} 的处理函数 {handler.handler_name} 时出现异常:{e}"
                     event.set_result(MessageEventResult().message(ret))
</code_context>

<issue_to_address>
**suggestion (bug_risk):** Align error-reply suppression logic with the documented `event.stop_event()` behavior.

The docstring for `register_on_plugin_error` promises that `event.stop_event()` suppresses the default error reply, but this implementation instead relies on `call_event_hook`’s return value (`suppress_default_error_reply`). That ties behavior to a helper’s return convention rather than the event state.

Consider checking the event state after the hook call:

```python
await call_event_hook(...)

if not event.is_stopped and event.is_at_or_wake_command:
    ...
```

Alternatively, if you keep using the return value, ensure `call_event_hook` explicitly returns `event.is_stopped` and document that contract so it matches the docstring.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@dosubot dosubot bot added the area:core The bug / feature is about astrbot's core, backend label Feb 18, 2026
@dosubot dosubot bot added the lgtm This PR has been approved by a maintainer label Feb 18, 2026
@Soulter Soulter merged commit c6289d8 into AstrBotDevs:master Feb 18, 2026
6 checks passed
united-pooh pushed a commit to united-pooh/AstrBot that referenced this pull request Feb 19, 2026
…vs#5192)

* feat(core): add plugin error hook for custom error routing

* fix(core): align plugin error suppression with event stop state
Raven95676 added a commit to Raven95676/AstrBot_Rdev that referenced this pull request Feb 20, 2026
- Integrate active_event_registry register/unregister into new
  PipelineExecutor to restore AstrBotDevs#5225 (terminate active events on
  reset/new/del)
- Add missing component validators (Json, Share, Music, Forward,
  Location, Contact, Shake, Dice, RPS, Unknown) to SendService
  to restore AstrBotDevs#5208 (JSON-only message empty reply error)
- Invoke OnPluginErrorEvent hook in CommandDispatcher error path
  to restore AstrBotDevs#5192 (plugin error hook for custom error routing)
- Pass text=comp.text when creating TTS Record to restore AstrBotDevs#5204
  (voice_messages_forbidden fallback caption on Telegram)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:core The bug / feature is about astrbot's core, backend lgtm This PR has been approved by a maintainer size:M This PR changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]允许屏蔽报错并且发到指定会话

2 participants