Skip to main content

Gateway restart is impossible from inside the gateway; updater leaves it manual

entry

Date: 2026-09-16 Lane: hermes Source: observed on Zappo (macbook-pro-3, 100.80.168.13) during hermes_openclaw_auto_upgrade.py --apply

What happened​

hermes_openclaw_auto_upgrade.py --apply ran hermes update --yes --backup. The update pulled 2156 commits and rebuilt the checkout correctly (v0.21.1 -> v0.21.3, HEAD f97a4102dd -> 5d59366010), then reported:

⚠ Update incomplete — gateway auto-restart failed: cannot import name 'file_signature' from 'utils'
Any gateway still running is serving pre-update code (mixed sys.modules) against the updated checkout.

The import error is a red herring for the code state. from utils import file_signature succeeds in the updated checkout when tested directly; utils.py:38 defines file_signature. The failure is a stale sys.modules artifact in the running (old) gateway process, exactly what the message describes.

Result state: checkout at 5d59366010 (v0.21.3), live gateway still stamping code_version: 0.21.1, code_sha: f97a4102dd in ~/.hermes/gateway_state.json. The updater left ~/.hermes/fleet_restart_pending with expected_sha=5d59366010... and classified the restart mechanism as manual.

The blocking fact​

A gateway restart cannot be issued from a process descended from the gateway. hermes gateway restart inside the gateway returns:

Blocked: command or referenced script cannot restart, stop, or uninstall the gateway from inside the gateway process. The gateway would kill this command before it could complete (SIGTERM propagates to child processes).

launchctl submit/bootstrap is blocked by the same guard regardless of job label. The guard is deliberate and must not be worked around. When the updater itself is launched as a background process from a gateway session, it inherits the gateway's process tree, so the restart phase is classified manual and never runs.

Rules​

  1. Run the auto-upgrade outside the gateway process tree, or accept that the restart stays manual. A terminal(background=true) process spawned from a gateway session is still a gateway descendant and does not escape the guard.
  2. Never treat "update exit=1" as a failed upgrade. Read ~/.hermes/logs/update.log: the pull phase can fully succeed and only the restart phase fail. Confirm the checkout with git -C ~/.hermes/hermes-agent rev-parse --short HEAD.
  3. Verify a completed upgrade by comparing code_version/code_sha in ~/.hermes/gateway_state.json against the checkout. Equal versions is the only healthy state; a stale gateway is a mixed-version fleet.
  4. ~/.hermes/fleet_restart_pending present means a restart is owed. It is cleared by a successful restart, not by hand.
  5. The gateway must be restarted from a terminal outside the gateway (a plain login shell, not a Hermes session), then verified with hermes gateway status.

OpenClaw is gated on Node, not on the updater​

OpenClaw could not update: Node 22.22.3 is too old for openclaw@2026.9.4. The requested package requires >=24.16.0 \<25 || >=26.1.0. Both /usr/local/bin/node and the Node that OpenClaw runs under (~/.npm-global/lib/node_modules/node/bin/node) are v22.22.3. The Node upgrade is a separate, previously flagged decision. Until then OpenClaw stays on 2026.8.1. Do not run bare npm i -g openclaw as a workaround; it can silently install an older compatible release.