Summary
After upgrading to OpenClaw 2026.5.2 and installing the now-external @openclaw/bluebubbles plugin, inbound iMessages are dropped when channels.bluebubbles.password is configured as a SecretRef (e.g. {source: "exec", provider: "...", id: "value"}). The webhook route registers and listens, but every POST is rejected with:
plugin http route failed (bluebubbles): TypeError: target.account.config.password?.trim is not a function
Outbound sends and the BlueBubbles HTTP API still work (they go through createBlueBubblesClientFromParts which calls normalizeSecretInputString). Only the webhook auth path is broken.
Root cause
extensions/bluebubbles/src/monitor.ts line ~196 (in the new external @openclaw/bluebubbles plugin v2026.5.2):
const token = target.account.config.password?.trim() ?? "";
return safeEqualAuthToken(guid, token);
When password is a SecretRef object, .trim is undefined and the route handler throws. Every other consumer of account.config.password in this plugin (monitor-processing.ts:780, actions.ts:159, account-resolve.ts:49) uses normalizeSecretInputString(account.config.password) to coerce SecretRef → string before use. The webhook auth path missed it.
Reproduction
- OpenClaw 2026.5.2, install plugin:
openclaw plugins install @openclaw/bluebubbles
~/.openclaw/openclaw.json:
"channels": {
"bluebubbles": {
"enabled": true,
"webhookPath": "/bluebubbles-webhook",
"serverUrl": "http://localhost:1234",
"password": { "source": "exec", "provider": "op-bb-password", "id": "value" }
}
}
- Restart gateway. Logs show
BlueBubbles webhook listening on /bluebubbles-webhook.
- Send an iMessage to the bridged number. BlueBubbles fires its webhook → gateway logs
plugin http route failed (bluebubbles): TypeError: target.account.config.password?.trim is not a function. Message never reaches the agent.
Also at startup:
[default] BlueBubbles catchup: cannot resolve server account: Error: channels.bluebubbles.password: unresolved SecretRef "exec:op-bb-password:value". Resolve this command against an active gateway runtime snapshot before reading it.
— suggests catchup may have the same issue (resolving SecretRef without going through the runtime resolver).
Suggested fix
In monitor.ts, replace the raw .trim() with normalizeSecretInputString(target.account.config.password)?.trim() ?? "" (or use whatever the runtime-resolved password helper is — same one createBlueBubblesClientFromParts uses on the outbound side). Audit other call sites for the same pattern; catchup.ts:405 and monitor.ts:342 also pass account.config.password raw.
Workaround
Replace the SecretRef with the literal password string in openclaw.json. Survives until plugin updates.
Environment
- OpenClaw 2026.5.2 (8b2a6e5)
@openclaw/bluebubbles 2026.5.2 (npm install, stable channel)
- macOS 26.4.1 (Tahoe)
- BlueBubbles server 1.9.9
- Single-host loopback gateway, password sourced via 1Password service-account exec wrapper
Summary
After upgrading to OpenClaw 2026.5.2 and installing the now-external
@openclaw/bluebubblesplugin, inbound iMessages are dropped whenchannels.bluebubbles.passwordis configured as a SecretRef (e.g.{source: "exec", provider: "...", id: "value"}). The webhook route registers and listens, but every POST is rejected with:Outbound sends and the BlueBubbles HTTP API still work (they go through
createBlueBubblesClientFromPartswhich callsnormalizeSecretInputString). Only the webhook auth path is broken.Root cause
extensions/bluebubbles/src/monitor.tsline ~196 (in the new external@openclaw/bluebubblesplugin v2026.5.2):When
passwordis a SecretRef object,.trimis undefined and the route handler throws. Every other consumer ofaccount.config.passwordin this plugin (monitor-processing.ts:780,actions.ts:159,account-resolve.ts:49) usesnormalizeSecretInputString(account.config.password)to coerce SecretRef → string before use. The webhook auth path missed it.Reproduction
openclaw plugins install @openclaw/bluebubbles~/.openclaw/openclaw.json:BlueBubbles webhook listening on /bluebubbles-webhook.plugin http route failed (bluebubbles): TypeError: target.account.config.password?.trim is not a function. Message never reaches the agent.Also at startup:
— suggests catchup may have the same issue (resolving SecretRef without going through the runtime resolver).
Suggested fix
In
monitor.ts, replace the raw.trim()withnormalizeSecretInputString(target.account.config.password)?.trim() ?? ""(or use whatever the runtime-resolved password helper is — same onecreateBlueBubblesClientFromPartsuses on the outbound side). Audit other call sites for the same pattern;catchup.ts:405andmonitor.ts:342also passaccount.config.passwordraw.Workaround
Replace the SecretRef with the literal password string in
openclaw.json. Survives until plugin updates.Environment
@openclaw/bluebubbles2026.5.2 (npm install, stable channel)