Skip to content

fix: preserve plugin-registered internal hooks across gateway startup#26184

Closed
white-rm wants to merge 1 commit intoopenclaw:mainfrom
white-rm:fix/plugin-registerHook-never-fires-25859
Closed

fix: preserve plugin-registered internal hooks across gateway startup#26184
white-rm wants to merge 1 commit intoopenclaw:mainfrom
white-rm:fix/plugin-registerHook-never-fires-25859

Conversation

@white-rm
Copy link
Copy Markdown

@white-rm white-rm commented Feb 25, 2026

Summary

Fixes #25859

Plugin hooks registered via api.registerHook("message:received", ...) were visible in openclaw hooks list but never fired. The root cause is a startup ordering issue:

  1. loadGatewayPlugins() runs first — plugins register handlers into the internal hooks Map via registerInternalHook()
  2. startGatewaySidecars() runs later — clearInternalHooks() wipes all handlers, then loadInternalHooks() only reloads directory-discovered hooks, not plugin-registered ones
  3. Plugin hook handlers are permanently lost

Changes

  • src/plugins/registry.ts: Store the handler reference in PluginHookRegistration so it survives the clear cycle. Add reregisterPluginInternalHooks() helper that re-registers plugin hooks from the registry.
  • src/gateway/server-startup.ts: Call reregisterPluginInternalHooks() after clearInternalHooks() + loadInternalHooks() to restore plugin hooks. Log output now includes plugin hook count.

Test plan

  • Existing internal-hooks.test.ts tests pass (29/29)
  • TypeScript type-check passes (no new errors)
  • Manual: create a plugin with api.registerHook("message:received", ...), restart gateway, send a message — hook should fire

Greptile Summary

This PR fixes a startup ordering bug where plugin-registered internal hooks (via api.registerHook()) were permanently lost during gateway initialization. The fix stores handler references in the plugin registry and re-registers them after clearInternalHooks() wipes the internal hooks Map.

Key changes:

  • Added optional handler field to PluginHookRegistration type to preserve the handler function reference
  • New reregisterPluginInternalHooks() helper iterates the plugin registry and re-registers all stored handlers
  • Gateway startup now calls reregisterPluginInternalHooks() after directory-based hook loading completes
  • Log output updated to show total hook count including plugin-registered hooks

Confidence Score: 5/5

  • This PR is safe to merge with minimal risk
  • The fix is surgical and addresses a clear bug with a straightforward solution. The changes preserve handler references that were already being registered, and the re-registration happens at the correct point in the startup sequence. Type safety is maintained through the use of Parameters<typeof registerInternalHook>[1] for the handler type. The implementation follows the existing patterns and doesn't introduce new complexity.
  • No files require special attention

Last reviewed commit: 5704cb2

(4/5) You can add custom instructions or style guidelines for the agent here!

@openclaw-barnacle openclaw-barnacle bot added gateway Gateway runtime size: XS labels Feb 25, 2026
@white-rm
Copy link
Copy Markdown
Author

@steipete could u help me to review this pr? i think it's an useful suggestion

@steipete
Copy link
Copy Markdown
Contributor

steipete commented Mar 3, 2026

Closing as duplicate of #29515.

Same bug/fix target (api.registerHook handlers lost during gateway startup clear/reload), and #29515 has the cleaner current CI signal.

@steipete steipete closed this Mar 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gateway Gateway runtime size: XS

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Plugin api.registerHook("message:received", ...) shows up in openclaw hooks list but never fires (likely cleared at gateway startup)

3 participants