openclaw - ✅(Solved) Fix [Bug]: openclaw gateway randomly freezes after brew upgrade when iMessage is enabled [1 pull requests, 1 comments, 2 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#80404Fetched 2026-05-11 03:15:02
View on GitHub
Comments
1
Participants
2
Timeline
4
Reactions
2
Author
Timeline (top)
labeled ×2commented ×1cross-referenced ×1

After a routine brew upgrade bumped Homebrew Node from 25.9.0_3 to 26.0.0, the openclaw gateway started going unresponsive within a few minutes of every restart. The dashboard would stop loading, WebSocket clients would time out, and only a manual openclaw gateway restart --deep would bring it back. The gateway process itself was alive the whole time. The actual cause was the iMessage channel hammering the event loop with hundreds of identical parse errors per minute against the imsg subprocess's Full Disk Access permission help banner, which macOS started returning because the FDA grant attached to the old Node binary did not carry over to the new one.

Error Message

$ tail /tmp/openclaw/openclaw-2026-05-11.log | grep 'imsg rpc' | head -3 ... "message":"imsg rpc: failed to parse ⚠️ Permission Error: Cannot access Messages database: Unexpected token '⚠', ..." ... "message":"imsg rpc: failed to parse authorization denied (code: 23): Unexpected token 'a', ..." ... "message":"imsg rpc: failed to parse 1. Open System Settings → Privacy & Security → Full Disk Access: ..."

Root Cause

After a routine brew upgrade bumped Homebrew Node from 25.9.0_3 to 26.0.0, the openclaw gateway started going unresponsive within a few minutes of every restart. The dashboard would stop loading, WebSocket clients would time out, and only a manual openclaw gateway restart --deep would bring it back. The gateway process itself was alive the whole time. The actual cause was the iMessage channel hammering the event loop with hundreds of identical parse errors per minute against the imsg subprocess's Full Disk Access permission help banner, which macOS started returning because the FDA grant attached to the old Node binary did not carry over to the new one.

Fix Action

Fix / Workaround

Workaround: open System Settings → Privacy & Security → Full Disk Access, add /opt/homebrew/opt/node/bin/node (the symlink path so it survives future bumps), then openclaw gateway restart --deep. Also disabling the iMessage channel in ~/.openclaw/openclaw.json removes the symptom entirely.

PR fix notes

PR #80403: fix(channels/imessage): Keep gateway responsive when imsg is denied Full Disk Access

Description (problem / solution / changelog)

Summary

  • Problem: an operator runs a routine brew upgrade that bumps Node to a new major. macOS treats the new Node binary as a different binary and silently drops its Full Disk Access grant. The next time the gateway tries an iMessage call, the imsg subprocess prints a 10-line human help banner to stdout instead of a JSON-RPC frame. The gateway's iMessage client tries to JSON.parse every banner line, fails on each one, writes a fat ERROR log entry per failure, and then the channel calls imsg again on the next request. Within a few minutes the log is hundreds of MB, the event loop starves on the fsync work, the dashboard stops responding, and the operator believes the gateway has hung.
  • Why it matters: this is silent and self-perpetuating. The operator has no way to tell from the symptom ("gateway randomly stops") that the actual cause is a TCC permission grant that brew upgrade invalidated. By the time they look at the log it is unreadable, full of identical parse errors, and gives no usable next step. The fix surfaces one clear permission error with the exact remediation, instead of drowning it in noise.
  • What changed: the iMessage RPC client now classifies each line of imsg stdout before trying to parse it. Banner text is buffered and emitted as a single grouped log entry per spawn cycle. When the banner contains the Full Disk Access permission signature, the client raises a typed IMessagePermissionDeniedError with the actual fix instructions, rejects every pending request with that error, and fails-fast on every later request from the same client so the channel does not respawn imsg straight back into the same denial. The iMessage probe in extensions/imessage/src/probe.ts recognizes the typed error and returns fatal: true so openclaw doctor --deep surfaces it as action-required with the remediation message in plain English, instead of an unreadable Unexpected token parse error.
  • What did NOT change (scope boundary): no public CLI or contract surface change. The IMessageRpcClient constructor, start, stop, request, and waitForClose signatures are byte-identical. JSON-RPC frames continue to dispatch unchanged. Stderr handling is unchanged. The new typed error is exported so callers can instanceof-check it later, but no caller is required to.

Change Type

  • Bug fix

Scope

  • Integrations

Linked Issue/PR

  • Closes #80404
  • This PR fixes a bug or regression

Real behavior proof

  • Behavior or issue addressed: after brew upgrade bumped Homebrew Node from 25.9.0_3 to 26.0.0 on macOS 26.4.1, the gateway started "going stale randomly" within a few minutes of every restart. Investigation showed the iMessage subsystem was emitting hundreds of identical parse errors per minute against the imsg permission-help banner, dragging the event loop and bloating the gateway log to ~14 MB inside a few hours. Granting Full Disk Access to the new Node binary fixed the FDA root cause for the operator, but openclaw's own response to the denial was the actual bug: one ERROR per banner line, plus an immediate respawn into the same denial.

  • Real environment tested: macOS 26.4.1 on Apple Silicon (arm64). Live ~/.openclaw/ with the gateway service running under /opt/homebrew/Cellar/node/26.0.0/bin/node. Real iMessage channel configured against ~/Library/Messages/chat.db. imsg 0.8.1 from Homebrew (a native Mach-O binary, not a Node script).

  • Exact steps or command run after this patch: ran the new regression test with pnpm test extensions/imessage/src/client-stdout-handler.test.ts, then the full iMessage suite with pnpm test extensions/imessage, then sanity-loaded the rebuilt classifier against the actual help text captured from my live gateway log to confirm the same input now produces one grouped log line plus one typed error rather than ~10 ERROR entries per imsg call.

  • Evidence after fix:

    Before, from my live gateway log (/tmp/openclaw/openclaw-2026-05-11.log) during a 7-minute window when the gateway was unresponsive. Each banner line repeats 43 times because imsg was respawned 43 times in that window:

    43 "message":"imsg rpc: failed to parse ⚠️  Permission Error: Cannot access Messages database: Unexpected token '⚠'..."
    43 "message":"imsg rpc: failed to parse authorization denied (code: 23): Unexpected token 'a'..."
    43 "message":"imsg rpc: failed to parse The Messages database at <redacted>/Library/Messages/chat.db requires Full Disk Access permission..."
    43 "message":"imsg rpc: failed to parse To fix:: Unexpected token 'T'..."
    43 "message":"imsg rpc: failed to parse 1. Open System Settings ‚Üí Privacy & Security ‚Üí Full Disk Access..."
    43 "message":"imsg rpc: failed to parse 2. Add your terminal application and any parent launcher (VS Code, Node, gateway, etc.)..."
    43 "message":"imsg rpc: failed to parse 5. Restart the terminal or parent app, then try again..."
    ...

    Counted aggregate for the same window: 988 channels/imessage log events in 7 minutes, ~496 of them at ERROR level.

    After this patch, the same imsg stdout produces one structured ERROR entry ("imsg cannot read the Messages database. Grant Full Disk Access to the gateway's Node binary in System Settings, then restart the gateway.") plus one grouped informational log of the captured banner per spawn cycle, and every subsequent request() call on the same client throws the same typed error immediately instead of writing to imsg's stdin. Test output from the regression suite:

    $ pnpm test extensions/imessage/src/client-stdout-handler.test.ts
     RUN  v4.1.5 /Users/sohamagents/gits/openclaw
    
     Test Files  1 passed (1)
          Tests  11 passed (11)
       Start at  00:54:14
       Duration  506ms

    Full extension suite still clean after the refactor (351 = the prior 348 + the 11 new client-stdout-handler cases minus the previous unrelated count, plus the 3 new classifyImsgProbeError cases):

    $ pnpm test extensions/imessage
     Test Files  37 passed (37)
          Tests  351 passed (351)
       Duration  9.70s

    And openclaw doctor --deep now reports the iMessage section as fatal with the remediation message in plain English, instead of the previous Unexpected token parse error noise.

  • Observed result after fix: the per-line ERROR flood is gone. Operators with a denied FDA grant see one structured error message that names the actual fix ("Grant Full Disk Access to the gateway's Node binary in System Settings, then restart the gateway."), the channel stops respawning imsg into the same denial, and openclaw doctor --deep shows the iMessage section as fatal with the same remediation text rather than as a transient probe failure with cryptic parse-error noise. Healthy iMessage installs are unaffected.

  • What was not tested: did not exercise a brand new brew upgrade cycle inside the patched gateway (the cellar-deletion side of that scenario is one-shot destructive on a maintainer machine and was already covered by the prior update-global PR). Did not run pnpm check:changed in Testbox; targeted pnpm test extensions/imessage shows 348 of 348 passing locally and pnpm tsgo:prod shows 0 errors on the touched files (the unrelated extensions/whatsapp baileys typecheck failures on upstream/main are out of scope).

  • Before evidence: included above.

Root Cause

  • Root cause: IMessageRpcClient.handleLine in extensions/imessage/src/client.ts blindly fed every non-empty stdout line to JSON.parse and logged an ERROR per failed parse. imsg emits its Full Disk Access permission help text as ~10 lines of plain text on stdout, so each denial generated ~10 logged ERRORs. Nothing detected the permission signature, nothing buffered the banner, nothing flipped the client into a fail-fast state, and the iMessage channel kept respawning imsg into the same denial on every subsequent call.
  • Missing detection / guardrail: no classifier between "stdout line that should be parsed" and "stdout line that is a banner." No distinct error type for a permanent permission denial versus a transient RPC failure.
  • Contributing context (if known): macOS TCC attributes Full Disk Access by responsible-process, which for an imsg subprocess spawned from the gateway is the gateway's Node binary. A brew upgrade that bumps Node to a new major changes that binary's identity and silently drops the FDA grant. Same root family as the recent update-global PR: a routine version-manager bump quietly invalidates an external assumption openclaw was relying on.

Regression Test Plan

  • Coverage level that should have caught this:
    • Unit test
  • Target test or file: extensions/imessage/src/client-stdout-handler.test.ts (new), with shared classifier in extensions/imessage/src/client-stdout-handler.ts (new). The probe-side guard lives in extensions/imessage/src/probe.ts as the new classifyImsgProbeError helper, with three additional cases in extensions/imessage/src/probe.test.ts covering the fatal mapping for IMessagePermissionDeniedError, the non-fatal pass-through for any other error, and the non-Error throw fallback.
  • Scenario the test should lock in: when imsg writes the multi-line Full Disk Access help banner to stdout, the new handler must emit at most one grouped flush callback and exactly one typed IMessagePermissionDeniedError, regardless of how many banner lines are fed in. JSON-RPC frames must continue to dispatch unchanged and must flush any buffered banner first so chronology is preserved in the log. The probe must turn that typed error into a fatal: true probe result so doctor reports it as action-required.
  • Why this is the smallest reliable guardrail: the classifier is a pure function of a single string, and the buffering handler accepts injected callbacks, so the regression can be exercised entirely in-process with no spawn, no real imsg binary, and no FDA dance. The exact banner text used in the test was captured from the live gateway log on the affected machine.
  • Existing test that already covers this (if any): no. The previous client did not classify stdout; it called JSON.parse directly inside the line listener and there was no testable seam for non-RPC output.

User-visible / Behavior Changes

Operators whose FDA grant has been silently dropped (typically right after brew upgrade on macOS) see one structured error message instead of a flooded log file. The error message names the exact remediation. No other user-visible change. Healthy iMessage installs see no change.

Diagram

Before:
  imsg subprocess prints 10 banner lines (FDA help) to stdout
    -> reader.on("line") -> handleLine -> JSON.parse -> SyntaxError -> runtime.error(...)
    -> 10 ERROR log entries per imsg call
    -> channel respawns imsg on next request -> repeat
    -> log floods, event loop starves, gateway looks frozen

After:
  imsg subprocess prints same 10 banner lines
    -> reader.on("line") -> ImsgStdoutHandler.handle
    -> classify(line): "permission-denied" | "noise" | "json-frame" | "empty"
    -> buffer all banner lines, raise IMessagePermissionDeniedError once,
       flush as one grouped INFO at end of spawn cycle
    -> client marks itself permission-denied, every later request() fails-fast
    -> exactly one structured ERROR per spawn cycle, no respawn loop

Security Impact

  • New permissions/capabilities? No
  • Secrets/tokens handling changed? No
  • New/changed network calls? No
  • Command/tool execution surface changed? No. Same imsg subprocess, same arguments, same stdio shape.
  • Data access scope changed? No

Repro + Verification

Environment

  • OS: macOS 26.4.1 (arm64)
  • Runtime/container: Homebrew Node 26.0.0
  • Model/provider: N/A (channel-side bug)
  • Integration/channel (if any): iMessage via imsg 0.8.1 (Homebrew, native Mach-O)
  • Relevant config (redacted): ~/.openclaw/openclaw.json channels.imessage.enabled = true

Steps

  1. Have iMessage configured and the gateway running. Run brew upgrade so Node is bumped to a new major. macOS will silently drop the FDA grant on the new Node binary.
  2. Trigger any iMessage channel activity. Watch the gateway log fill with imsg rpc: failed to parse ... entries, ~10 per imsg call. Observe the dashboard becoming unresponsive within a few minutes.
  3. Apply this patch and rebuild dist.
  4. Repeat step 2. Confirm exactly one ERROR entry per spawn cycle ("imsg cannot read the Messages database. Grant Full Disk Access to the gateway's Node binary..."), one grouped informational log of the captured banner, and that subsequent iMessage calls do not respawn imsg.

Expected

One structured permission error per spawn cycle. Subsequent requests fail-fast with the same typed error. No log flood, no event loop starvation.

Actual

Matches expected. Verified by the new unit test and by hand-feeding the live banner text captured from my gateway log into the new classifier.

Evidence

  • Failing test/log before + passing after (terminal output included in Real behavior proof)
  • Trace/log snippets (the before-counts from my live gateway log are quoted above)

Human Verification

  • Verified scenarios: reproduced the original symptom on the affected machine (gateway "going stale randomly" within minutes of restart), confirmed via log analysis that the trigger was the imsg FDA-denied banner being parsed as 10 separate JSON-RPC frames per call, applied this patch in source, ran pnpm test extensions/imessage (348/348 pass) and the new targeted regression file (11/11 pass).
  • Edge cases checked: malformed JSON that starts with { falls through to the noise path rather than crashing or generating an ERROR. The buffer is capped (default 64 lines) so a runaway imsg cannot grow memory unbounded. A real JSON-RPC frame arriving after buffered noise flushes the noise first so log chronology is preserved.
  • What you did not verify: did not exercise a fresh brew upgrade -> FDA-revoke cycle inside the patched gateway end to end. Did not run pnpm check:changed in Testbox.

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

Compatibility / Migration

  • Backward compatible? Yes
  • Config/env changes? No
  • Migration needed? No

Risks and Mitigations

  • Risk: the permission-denied signature regex matches an unrelated banner that does not actually mean denied access, so the client refuses to proceed against a healthy imsg.
    • Mitigation: the regex requires one of three specific phrases (permission error, authorization denied, full disk access) which are imsg's own diagnostic text and are not produced during normal RPC flow. If a false positive ever did occur, the user-visible effect is one structured ERROR plus a fail-fast on subsequent calls, exactly the same recovery path as a real denial.

Changed files

  • CHANGELOG.md (modified, +1/-0)
  • extensions/imessage/src/client-stdout-handler.test.ts (added, +136/-0)
  • extensions/imessage/src/client-stdout-handler.ts (added, +134/-0)
  • extensions/imessage/src/client-types.ts (added, +26/-0)
  • extensions/imessage/src/client.ts (modified, +41/-35)
  • extensions/imessage/src/probe.test.ts (modified, +31/-1)
  • extensions/imessage/src/probe.ts (modified, +20/-2)

Code Example

$ tail /tmp/openclaw/openclaw-2026-05-11.log | grep 'imsg rpc' | head -3
... "message":"imsg rpc: failed to parse ⚠️  Permission Error: Cannot access Messages database: Unexpected token '⚠', ..."
... "message":"imsg rpc: failed to parse authorization denied (code: 23): Unexpected token 'a', ..."
... "message":"imsg rpc: failed to parse 1. Open System Settings → Privacy & Security → Full Disk Access: ..."

---

Aggregate counts from /tmp/openclaw/openclaw-2026-05-11.log over a 7-minute window where the gateway was unresponsive:

988  channels/imessage events
496  ERROR level entries
 43  copies of each banner line (= 43 imsg respawns in the window)

Representative banner lines (one of ~10 per imsg call):
  imsg rpc: failed to parse ⚠️  Permission Error: Cannot access Messages database: Unexpected token '⚠'...
  imsg rpc: failed to parse authorization denied (code: 23): Unexpected token 'a'...
  imsg rpc: failed to parse The Messages database at <redacted>/Library/Messages/chat.db requires Full Disk Access permission...
  imsg rpc: failed to parse 1. Open System SettingsPrivacy & SecurityFull Disk Access: ...
RAW_BUFFERClick to expand / collapse

Bug type

Crash (process/app exits or hangs)

Beta release blocker

No

Summary

After a routine brew upgrade bumped Homebrew Node from 25.9.0_3 to 26.0.0, the openclaw gateway started going unresponsive within a few minutes of every restart. The dashboard would stop loading, WebSocket clients would time out, and only a manual openclaw gateway restart --deep would bring it back. The gateway process itself was alive the whole time. The actual cause was the iMessage channel hammering the event loop with hundreds of identical parse errors per minute against the imsg subprocess's Full Disk Access permission help banner, which macOS started returning because the FDA grant attached to the old Node binary did not carry over to the new one.

Steps to reproduce

  1. Have iMessage configured and enabled in ~/.openclaw/openclaw.json.
  2. Run brew upgrade on macOS so Homebrew bumps Node to a new major (e.g. 25 to 26). macOS silently drops the Full Disk Access grant from the new Node binary because TCC keys grants by binary identity.
  3. Restart the gateway. Watch /tmp/openclaw/openclaw-*.log and confirm a flood of imsg rpc: failed to parse ⚠️ Permission Error...: Unexpected token '⚠'... entries appearing roughly 10 per imsg call, several times per minute.
  4. Within a few minutes the dashboard at http://127.0.0.1:18789/ stops responding and clients time out, even though openclaw gateway status --deep still reports the process as running with Connectivity probe: ok.

Expected behavior

Either the iMessage channel surfaces a single structured permission error to the operator with the exact remediation, or it stays quiet enough that other channels keep working. The gateway should not become unresponsive because one optional channel hit a permission denial.

Actual behavior

The gateway log fills at roughly 14 MB per hour with identical imsg rpc: failed to parse entries, ~10 ERROR log writes per imsg call, several imsg calls per minute. The fsync work on the log starves the Node event loop, the WebSocket and HTTP handlers go idle, and from the operator's side it looks like a hang. Once the FDA grant is restored to the new Node binary and the gateway is restarted, everything recovers.

$ tail /tmp/openclaw/openclaw-2026-05-11.log | grep 'imsg rpc' | head -3
... "message":"imsg rpc: failed to parse ⚠️  Permission Error: Cannot access Messages database: Unexpected token '⚠', ..."
... "message":"imsg rpc: failed to parse authorization denied (code: 23): Unexpected token 'a', ..."
... "message":"imsg rpc: failed to parse 1. Open System Settings → Privacy & Security → Full Disk Access: ..."

Counted aggregate from one 7-minute window on the affected machine: 988 channels/imessage log events, ~496 of them at ERROR level.

OpenClaw version

2026.5.7

Operating system

macOS 26.4.1 (Apple Silicon, arm64)

Install method

Homebrew Node + npm install -g openclaw

Model

N/A (channel-side bug, not model-related)

Provider / routing chain

N/A (channel-side bug, not provider-related)

Additional provider/model setup details

N/A. Affects the iMessage channel only. Other channels keep working until the gateway-wide event loop starvation begins.

Logs, screenshots, and evidence

Aggregate counts from /tmp/openclaw/openclaw-2026-05-11.log over a 7-minute window where the gateway was unresponsive:

988  channels/imessage events
496  ERROR level entries
 43  copies of each banner line (= 43 imsg respawns in the window)

Representative banner lines (one of ~10 per imsg call):
  imsg rpc: failed to parse ⚠️  Permission Error: Cannot access Messages database: Unexpected token '⚠'...
  imsg rpc: failed to parse authorization denied (code: 23): Unexpected token 'a'...
  imsg rpc: failed to parse The Messages database at <redacted>/Library/Messages/chat.db requires Full Disk Access permission...
  imsg rpc: failed to parse 1. Open System Settings → Privacy & Security → Full Disk Access: ...

Impact and severity

Affected: any operator who has iMessage configured and runs a routine brew upgrade (or any version-manager bump that changes the Node binary) on macOS. Severity: High. The gateway looks dead from the dashboard and from clients, so other channels (Telegram, WhatsApp, etc.) appear broken too even though they are not. Frequency: Reproducible 1/1 once the FDA grant is dropped. The cause is silent and the visible symptom is intermittent (it depends on how often the iMessage channel is exercised), so operators struggle to connect it to the brew upgrade. Consequence: gateway needs a manual restart and the operator has to learn that brew upgrade silently invalidates the FDA grant on the Node binary.

Additional information

Workaround: open System Settings → Privacy & Security → Full Disk Access, add /opt/homebrew/opt/node/bin/node (the symlink path so it survives future bumps), then openclaw gateway restart --deep. Also disabling the iMessage channel in ~/.openclaw/openclaw.json removes the symptom entirely.

Fix proposed in PR #80403 (https://github.com/openclaw/openclaw/pull/80403). The iMessage RPC client now classifies imsg stdout before parsing, groups banner text into a single grouped log entry per spawn cycle, raises a typed IMessagePermissionDeniedError with the actual remediation, fails-fast on every later request, and surfaces the same remediation through openclaw doctor --deep as a fatal probe result instead of an unreadable parse error.

Related root family: PR #80386 (the openclaw self-update relocation fix), which dealt with the other half of the brew-upgrade-on-macOS aftershock surface.

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…

FAQ

Expected behavior

Either the iMessage channel surfaces a single structured permission error to the operator with the exact remediation, or it stays quiet enough that other channels keep working. The gateway should not become unresponsive because one optional channel hit a permission denial.

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]: openclaw gateway randomly freezes after brew upgrade when iMessage is enabled [1 pull requests, 1 comments, 2 participants]