Skip to content

Feature request: openclaw update should detect when invoked from inside the gateway process tree (PPID-ancestry guard) #75691

Description

@islandpreneur007

Summary

When openclaw update --tag <ver> --yes is invoked from a process whose parent process tree includes the active gateway PID (e.g., from inside an agent's exec subprocess), the package install and doctor migrations complete successfully, but the supervised-mode restart silently fails to take effect. The binary on disk is the new version while the gateway PID and in-memory code remain the old version, leaving the operator with no signal that anything went wrong.

Reproduction

  1. Run OpenClaw under systemd (system-level unit at /etc/systemd/system/openclaw.service, Restart=always)
  2. From inside an agent's exec tool (gateway is the agent's parent process), run:
    openclaw update --tag <newer-version> --yes
    
  3. Observe: install logs report success, doctor migrations apply, command exits 0.
  4. Verify in-memory state — the gateway PID is unchanged. The new code is on disk but not loaded.

Root cause

In dist/cli/gateway-lifecycle.runtime.js::restartGatewayProcessWithFreshPid(), when systemd is detected as the supervisor, the function returns { mode: "supervised" } and the caller is expected to exit. The architectural assumption is that the caller IS the gateway process — exiting triggers systemd's Restart=always to spawn the fresh process.

When the caller is a CHILD of the gateway (an agent's exec subprocess), child exit doesn't propagate to the gateway parent, systemd sees the gateway alive, and no restart fires.

Proposal

Make openclaw update walk its own ppid chain at startup. If the active gateway PID appears in the caller's ancestor PIDs:

Option A (defensive, smallest change): Refuse to perform the restart phase. Surface a clear error:

Error: openclaw update detected it is running inside the gateway process tree
(gateway PID <X> is an ancestor of this process). The supervised-mode restart
cannot fire from this context. Run `openclaw update` from an external shell
(SSH, cron, or other detached session). To install without restart from this
context, pass --no-restart and manually invoke `sudo systemctl restart <unit>`
from outside.

Option B (helpful, slightly larger change): Auto-defer the restart via a detached helper. Spawn nohup bash -c 'sleep 2 && systemctl restart <detected-unit>' &, then exit. Document that this only works if the active unit is system-level and the user has appropriate sudo.

Either solves the silent-failure mode. Option A is simpler and more conservative.

Why this matters

Operators running OpenClaw under any agent-orchestration pattern (HZL, Lobster, COO agents, etc.) will frequently invoke updates from inside the gateway-managed lane. The current behavior is a footgun: the update appears to succeed but the gateway keeps running old code. Without external monitoring, this can persist for hours or days.

Empirical evidence

From a 4.29 cutover at 2026-05-01 04:16-04:21 UTC:

  • An agent (Trent) ran openclaw update --tag 2026.4.29 --yes from its gateway-owned exec lane
  • Binary on disk: 2026.4.29 (openclaw --version confirmed)
  • systemctl show openclaw -p MainPID --value: 598350 (the OLD 4.27 process, unchanged)
  • Recovery: sudo systemctl restart openclaw.service from a fresh subprocess → MainPID changed to 605944

Same pattern observed on 4.26 cutover ~2026-04-28.

Workaround in place

Operating SOP "openclaw-update-native-v1" v3 now mandates external-lane invocation as primary, with in-lane B2a/B2b split (--no-restart install + external sudo systemctl restart openclaw.service) as fallback only.

Sister filing

Companion to a separate request for openclaw update to support system-level systemd units explicitly (currently the detached restart-script uses systemctl --user restart which doesn't control system-level units).

Metadata

Metadata

Assignees

No one assigned

    Labels

    In ProgressThis issue is already being worked on.

    Type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions