openclaw - ✅(Solved) Fix Bug: pluginConfig not injected into hook handler event context for api.registerHook [1 pull requests, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#72880Fetched 2026-04-28 06:30:59
View on GitHub
Comments
0
Participants
1
Timeline
8
Reactions
0
Participants
Timeline (top)
referenced ×6closed ×1cross-referenced ×1

When plugins register hooks via api.registerHook(), the pluginConfig from openclaw.json is not injected into the hook event context. Any plugin that accesses ctx.pluginConfig or event.context.pluginConfig inside a hook handler receives undefined.

Root Cause

When plugins register hooks via api.registerHook(), the pluginConfig from openclaw.json is not injected into the hook event context. Any plugin that accesses ctx.pluginConfig or event.context.pluginConfig inside a hook handler receives undefined.

Fix Action

Workaround

Plugins can capture api.pluginConfig at registration time via closure:

register(api) {
  const config = api.pluginConfig;
  api.registerHook("agent:bootstrap", async (event) => {
    const cfg = event.context.pluginConfig ?? config; // fallback to closure
  });
}

PR fix notes

PR #72888: fix: inject pluginConfig into hook handler event context

Description (problem / solution / changelog)

Problem

When plugins register hooks via api.registerHook(), the pluginConfig from openclaw.json is not injected into the hook event context. Any plugin that accesses event.context.pluginConfig inside a hook handler receives undefined.

Root Cause

In src/plugins/registry.ts:

  • registerHook() (line 419) passes the handler directly to registerInternalHook(event, handler) without wrapping — no pluginConfig is added to the event context
  • createApi() (line 1469) passes params.config but not params.pluginConfig to registerHook

Impact

  • Plugins that access ctx.pluginConfig in hook handlers silently get undefined
  • Plugins that fall back to defaults (ctx.pluginConfig ?? {}) ignore user configuration
  • api.pluginConfig is available at registration time but NOT at hook invocation time

Fix

  1. Add pluginConfig parameter to registerHook()
  2. Wrap the handler to inject pluginConfig into event.context before each invocation
  3. Pass params.pluginConfig through from createApi()

Testing

Verified locally on v2026.4.22 with a custom plugin (ava-bootstrap-inject) that reads pluginConfig.files from the hook context. Before patch: undefined → plugin was a silent no-op. After patch: config resolves correctly and files are injected.

Debug log confirming fix:

[ava-bootstrap-inject] hook fired. sessionKey=agent:main:main 
pluginConfig={"files":["memory/alive.md","memory/daily_focus.md","memory/session_primer.md"]} 
filesResolved=["memory/alive.md","memory/daily_focus.md","memory/session_primer.md"]

Fixes #72880

Changed files

  • src/plugins/loader.test.ts (modified, +60/-0)
  • src/plugins/registry.ts (modified, +9/-3)

Code Example

// registry.ts line 419 — add pluginConfig parameter
const registerHook = (
  record: PluginRecord,
  events: string | string[],
  handler: Parameters<typeof registerInternalHook>[1],
  opts: OpenClawPluginHookOptions | undefined,
  config: OpenClawPluginApi["config"],
  pluginConfig: unknown,  // <-- add this
) => {
  // ... existing code ...
  
  // line 502 — wrap handler to inject pluginConfig
  for (const event of normalizedEvents) {
    const wrappedHandler = async (evt: InternalHookEvent) => {
      if (evt.context && typeof evt.context === "object") {
        evt.context.pluginConfig = pluginConfig;
      }
      return handler(evt);
    };
    registerInternalHook(event, wrappedHandler);
    nextRegistrations.push({ event, handler: wrappedHandler });
  }

---

// line 1469 — pass pluginConfig
registerHook(record, events, handler, opts, params.config, params.pluginConfig),

---

register(api) {
  const config = api.pluginConfig;
  api.registerHook("agent:bootstrap", async (event) => {
    const cfg = event.context.pluginConfig ?? config; // fallback to closure
  });
}
RAW_BUFFERClick to expand / collapse

Summary

When plugins register hooks via api.registerHook(), the pluginConfig from openclaw.json is not injected into the hook event context. Any plugin that accesses ctx.pluginConfig or event.context.pluginConfig inside a hook handler receives undefined.

Affected Code

File: src/plugins/registry.ts

registerHook function (line 419): The handler is passed directly to registerInternalHook(event, handler) at line 502 without wrapping. The hook event context is built by createInternalHookEvent() which only sets workspaceDir, bootstrapFiles, cfg, sessionKey, sessionId, agentId — no pluginConfig.

createApi call site (line 1469): Passes params.config but not params.pluginConfig to registerHook.

Impact

  • Any plugin using api.registerHook() that needs to read its configured pluginConfig from the hook context will silently get undefined
  • api.pluginConfig is available at registration time but NOT at hook invocation time
  • Plugins that fall back to defaults still work but ignore user configuration
  • Plugins that guard on ctx.pluginConfig being defined silently no-op

Reproduction

  1. Create a plugin with a config schema and some config in openclaw.json
  2. Register a hook: api.registerHook("agent:bootstrap", async (event) => { const cfg = event.context.pluginConfig; /* undefined */ })
  3. Observe that pluginConfig is always undefined

Suggested Fix

Pass pluginConfig to registerHook and wrap the handler to inject it:

// registry.ts line 419 — add pluginConfig parameter
const registerHook = (
  record: PluginRecord,
  events: string | string[],
  handler: Parameters<typeof registerInternalHook>[1],
  opts: OpenClawPluginHookOptions | undefined,
  config: OpenClawPluginApi["config"],
  pluginConfig: unknown,  // <-- add this
) => {
  // ... existing code ...
  
  // line 502 — wrap handler to inject pluginConfig
  for (const event of normalizedEvents) {
    const wrappedHandler = async (evt: InternalHookEvent) => {
      if (evt.context && typeof evt.context === "object") {
        evt.context.pluginConfig = pluginConfig;
      }
      return handler(evt);
    };
    registerInternalHook(event, wrappedHandler);
    nextRegistrations.push({ event, handler: wrappedHandler });
  }
// line 1469 — pass pluginConfig
registerHook(record, events, handler, opts, params.config, params.pluginConfig),

Workaround

Plugins can capture api.pluginConfig at registration time via closure:

register(api) {
  const config = api.pluginConfig;
  api.registerHook("agent:bootstrap", async (event) => {
    const cfg = event.context.pluginConfig ?? config; // fallback to closure
  });
}

Versions

  • Reproduced on: 2026.4.22, 2026.4.25
  • Confirmed on main branch (registry.ts)

extent analysis

TL;DR

Pass pluginConfig to registerHook and wrap the handler to inject it into the hook event context.

Guidance

  • Update the registerHook function in registry.ts to accept a pluginConfig parameter and pass it to the wrapped handler.
  • Modify the createApi call site to pass params.pluginConfig to registerHook.
  • As a temporary workaround, plugins can capture api.pluginConfig at registration time via closure and use it as a fallback.
  • Verify the fix by checking that ctx.pluginConfig is no longer undefined in hook handlers.

Example

const registerHook = (
  record: PluginRecord,
  events: string | string[],
  handler: Parameters<typeof registerInternalHook>[1],
  opts: OpenClawPluginHookOptions | undefined,
  config: OpenClawPluginApi["config"],
  pluginConfig: unknown,  
) => {
  // ...
  const wrappedHandler = async (evt: InternalHookEvent) => {
    if (evt.context && typeof evt.context === "object") {
      evt.context.pluginConfig = pluginConfig;
    }
    return handler(evt);
  };
  // ...
}

Notes

This fix assumes that the pluginConfig is available at registration time and can be safely injected into the hook event context. If this is not the case, additional modifications may be necessary.

Recommendation

Apply the suggested fix by updating the registerHook function and createApi call site to pass pluginConfig and wrap the handler. This should resolve the issue and allow plugins to access their configured pluginConfig from the hook context.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - ✅(Solved) Fix Bug: pluginConfig not injected into hook handler event context for api.registerHook [1 pull requests, 1 participants]