Skip to content

[Bug]: in-band openclaw update on macOS LaunchAgent can stop the gateway supervising it #85120

Description

@amzzzzzzz

Summary

Running openclaw update from an in-band OpenClaw chat/tool session on a macOS LaunchAgent-managed gateway can stop the same gateway that is carrying the update command, dropping the session before the updater can supervise completion.

This is related to the broader durable-update handoff issues on Linux/systemd, but this report is the macOS/manual invocation variant: a user/agent starts openclaw update from inside the live OpenClaw runtime, the command reaches the gateway stop/restart phase, the webchat/tool session disconnects, and the update no longer has a durable owner.

Environment

  • OpenClaw upgraded to 2026.5.20
  • macOS, Apple Silicon
  • Gateway managed by LaunchAgent: ai.openclaw.gateway
  • Install/update path: global npm package
  • Invocation path: openclaw update initiated from a live OpenClaw webchat/tool session

What happened

During the first update attempt, the attached updater got as far as the gateway stop/restart phase. The gateway received a clean SIGTERM and webchat disconnected with service-restart semantics:

20:02:30 NDT gateway received SIGTERM
20:02:30 NDT webchat disconnected code=1012 reason=service restart
20:03:47 NDT gateway process present again
20:03:51 NDT gateway ready

A second restart window showed the same shape:

20:11:53 NDT gateway received SIGTERM
20:11:53 NDT webchat disconnected code=1012 reason=service restart
20:12:33 NDT gateway ready

A later supervised/manual package-manager path succeeded cleanly:

20:15:46 NDT final restart after manual install/plugin sync
20:15:57 NDT gateway ready

The key failure was not that the new release was broken. Once the update was run out-of-band, the system was healthy:

  • core OpenClaw 2026.5.20
  • gateway 2026.5.20
  • LaunchAgent loaded/running
  • dashboard reachable
  • BlueBubbles OK
  • Codex OAuth present
  • postflight healthy

Why this matters

For an operator using OpenClaw itself as the control surface, openclaw update is self-referential: it can stop the gateway/session transport that owns the command. A plain background child is not enough either; in our local experiment, a quick background-to-log attempt only wrote started and then died, because it was still owned by the dying process tree/session context.

The update needs a durable supervisor boundary before it stops/restarts the gateway.

Expected behavior

When openclaw update is invoked from a live OpenClaw/gateway-owned session on macOS LaunchAgent installs, it should either:

  1. hand off to a LaunchAgent/launchd-owned updater before stopping the gateway, then write a durable result file/log that survives the gateway restart, or
  2. detect that it is running from an in-band gateway/chat/tool context and refuse with a clear warning, e.g. "Run this from an external shell or submit an out-of-band update job."

Actual behavior

The update can proceed into gateway stop/restart while the command is still supervised by the live OpenClaw session. The chat/tool session drops, and the operator has to manually restart/check gateway state afterward.

Workaround that succeeded locally

We replaced the in-band update with an out-of-band wrapper:

  1. preflight backup
  2. submit a launchd-owned worker
  3. worker runs npm install -g openclaw@<target>
  4. plugin/peer sync
  5. exactly one openclaw gateway restart
  6. wait for gateway/version match
  7. run postflight
  8. write a timestamped log and JSON result file for the recovered chat session to read

This worked in dry/no-op validation and the direct package-manager/manual flow completed the 2026.5.20 update cleanly.

Related issues

This issue is specifically about the macOS LaunchAgent/manual openclaw update path when invoked from inside the live OpenClaw chat/tool runtime.

Suggested acceptance criteria

  • macOS LaunchAgent repro where openclaw update is invoked from an OpenClaw webchat/tool session and the update still completes with a durable result after gateway restart, or refuses before stopping the gateway.
  • A detached updater must be owned outside the dying gateway/session process tree. For macOS, that likely means launchd/LaunchAgent ownership rather than a plain background child.
  • The result should be visible after recovery through a status command, result file, or update status surface.
  • Existing systemd handoff fixes should not regress while adding the macOS LaunchAgent/manual path.

Metadata

Metadata

Assignees

Labels

P1High-priority user-facing bug, regression, or broken workflow.clawsweeper:needs-live-reproClawSweeper needs live local, crabbox, or manual validation to confirm this issue.impact:message-lossChannel message delivery can be lost, duplicated, or misrouted.impact:session-stateSession, memory, transcript, context, or agent state can drift or corrupt.issue-rating: 🐚 platinum hermitGood issue quality with a plausible reproduction path needing some confirmation.

Type

No type

Fields

Priority

None yet

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions