Gateway service restart exit code and systemd retry fixes
NousResearch/hermes-agent · cluster 14051 · gateway
Data as of
Nothing open on GitHub. Fix merged in #18639. Check it covers your case.
The short answer
- Known?
- Yes. 5 related items grouped here, 1 issue already closed.
- Fix event
- A fix was merged to main in PR #18639. Check it covers your case. No release data is tracked.
- Tracker
- The maintainers' tracker marks this
unresolved. That is separate from the fix event. - Still open
- Nothing open on GitHub.
These issues and PRs address how the gateway service signals restarts to systemd, including using a dedicated exit code to avoid exhausting StartLimitBurst and ensuring the systemd unit retries with appropriate backoff. Related changes also cover zombie PID detection during replacement and consistent use of the managed restart exit code on startup failure.
Open issues0
Open PRs0
Fixes on record
-
#18639 fix: gateway systemd unit now retries indefinitely with backoff
files:
hermes_cli/gateway.pyShow the diff
-
hermes_cli/gateway.py@@ -188,7 +188,7 @@ def _graceful_restart_via_sigusr1(pid: int, drain_timeout: float) -> bool: SIGUSR1 is wired in gateway/run.py to ``request_restart(via_service=True)`` which drains in-flight agent runs (up to ``agent.restart_drain_timeout`` - seconds), then exits with code 75. Both systemd (``Restart=on-failure`` + seconds), then exits with code 75. Both systemd (``Restart=always`` + ``RestartForceExitStatus=75``) and launchd (``KeepAlive.SuccessfulExit = false``) relaunch the process after the graceful exit. @@ -1655,8 +1655,7 @@ def generate_systemd_unit(system: bool = False, run_as_user: str | None = None) Description={SERVICE_DESCRIPTION} After=network-online.target Wants=network-online.target -StartLimitIntervalSec=600 -StartLimitBurst=5 +StartLimitIntervalSec=0 [Service] Type=simple @@ -1670,8 +1669,10 @@ def generate_systemd_unit(system: bool = False, run_as_user: str | None = None) Environment="PATH={sane_path}" Environment="VIRTUAL_ENV={venv_dir}" Environment="HERMES_HOME={hermes_home}" -Restart=on-failure -RestartSec=30 +Restart=always +RestartSec=60 +RestartMaxDelaySec=300 +RestartSteps=5 RestartForceExitStatus={GATEWAY_SERVICE_RESTART_EXIT_CODE} KillMode=mixed KillSignal=SIGTERM @@ -1691,9 +1692,9 @@ def generate_systemd_unit(system: bool = False, run_as_user: str | None = None) sane_path = ":".join(path_entries) return f"""[Unit] Description={SERVICE_DESCRIPTION} -After=network.target -StartLimitIntervalSec=600 -StartLimitBurst=5 +After=network-online.target +Wants=network-online.target +StartLimitIntervalSec=0 [Service] Type=simple @@ -1702,8 +1703,10 @@ def generate_systemd_unit(system: bool = False, run_as_user: str | None = None) Environment="PATH={sane_path}" Environment="VIRTUAL_ENV={venv_dir}" Environment="HERMES_HOME={hermes_home}" -Restart=on-failure -RestartSec=30 +Restart=always +RestartSec=60 +RestartMaxDelaySec=300 +RestartSteps=5 RestartForceExitStatus={GATEWAY_SERVICE_RESTART_EXIT_CODE} KillMode=mixed KillSignal=SIGTERM @@ -2451,7 +2454,7 @@ def run_gateway(verbose: int = 0, quiet: bool = False, replace: bool = False): print() # Exit with code 1 if gateway fails to connect any platform, - # so systemd Restart=on-failure will retry on transient errors + # so systemd Restart=always will retry on transient errors verbosity = None if quiet else verbose try: success = asyncio.run(start_gateway(replace=replace, verbosity=verbosity))
-
3 PRs closed without merging
From the close comments: done elsewhere 2 · other 1
-
#14069 fix(gateway): exit with RestartForceExitStatus code and detect zombie PIDs in --replace · other →
#14051,#13655 -
#14080 fix(gateway): use managed restart exit code on startup failure · done elsewhere →
#14051,#18639 -
#14260 fix(gateway): use GATEWAY_SERVICE_RESTART_EXIT_CODE instead of hardcoded 1 · done elsewhere →
#14051,#18639
Closed issues · 1
- Closed#14051Gateway service: exit code mismatch causes StartLimitBurst=5 exhaustion on rapid restart
How this cluster was grouped
-
Link evidence (
structural links throughout): every member is connected by structural evidence: shared changed files, or a closing/superseded reference. -
Pairwise link density
0.40: the share of item pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36.1.00means every pair is linked.
Pick up a Lab task
Check whether a fix covers the open issues here, with your own agent. Bring back evidence for maintainers.
Open the LabAt a glance
- Subsystem
- gateway
- Merged PRs
- #18639
- Closed issues
- 1
- Attempts
- 3 PRs closed without merging
- Fix link checked
- 2 May 2026