NousResearch/hermes-agent

systemd timeout mismatch and restart loop fixes

Cluster 31981 · gateway. Data as of

Nothing open on GitHub. Fix merged in #54066 on 28 Jun 2026. Check it covers your case.

The short answer

0open issues
0open PRs
4items grouped
Known?
Yes. 4 related items grouped here, 1 issue already closed.
Fix event
A fix was merged to main in PR #54066. Check it covers your case. No release data is tracked.
Tracker
The maintainers' tracker marks this resolved, deciding PR #54066. That is separate from the fix event.
Still open
Nothing open on GitHub.

These issues and PRs address a systemd TimeoutStopSec mismatch that causes silent crash or restart loops in the gateway, with proposed fixes including detection improvements, default timeout changes, subprocess cleanup, and the --replace flag.

Open issues0

No open issues.

Open PRs0

No open pull requests.

Fixes on record

Merged to main. A stamp counts the issues a fix is linked to.

  • #54066 fix(gateway): default restart_drain_timeout to 0 to kill systemd crash loop

    merged to main

    files: cli-config.yaml.example, gateway/run.py, hermes_cli/config.py, tests/gateway/test_gateway_shutdown.py

    Show the diff
    • cli-config.yaml.example
      @@ -626,10 +626,10 @@ agent:
         # gateway_timeout_warning: 900
       
         # Graceful drain timeout for gateway stop/restart (seconds).
      -  # The gateway stops accepting new work, waits for in-flight agents to
      -  # finish, then interrupts anything still running after this timeout.
      -  # 0 = no drain, interrupt immediately.
      -  # restart_drain_timeout: 60
      +  # Default 0 = no drain: a restart interrupts in-flight agents immediately,
      +  # cleans up, and exits. Set a positive value only if you want a grace
      +  # window on /restart, and keep it well under systemd's TimeoutStopSec.
      +  # restart_drain_timeout: 0
       
         # Max app-level retry attempts for API errors (connection drops, provider
         # timeouts, 5xx, etc.) before the agent surfaces the failure. Lower this
    • gateway/run.py
      @@ -5811,7 +5811,7 @@ async def start(self) -> bool:
                       logger.warning(
                           "Stale systemd unit detected: %s has TimeoutStopSec=%.0fs but "
                           "drain_timeout=%.0fs (expected >=%.0fs). systemd may SIGKILL the "
      -                    "gateway mid-drain. Run `hermes gateway service install --replace` "
      +                    "gateway mid-drain. Run `hermes gateway install --force` "
                           "to regenerate the unit, or shorten agent.restart_drain_timeout.",
                           _alignment.get("unit", "(unknown)"),
                           _alignment["timeout_stop_sec"],
    • hermes_cli/config.py
      @@ -916,13 +916,18 @@ def _ensure_hermes_home_managed(home: Path):
               # Graceful drain timeout for gateway stop/restart (seconds).
               # The gateway stops accepting new work, waits for running agents
               # to finish, then interrupts any remaining runs after the timeout.
      -        # 0 = no drain, interrupt immediately.
      +        # 0 = no drain, interrupt immediately (the default).
               #
      -        # 180s is calibrated for realistic in-flight agent turns: a typical
      -        # coding conversation mid-reasoning runs 60–150s per call, so a 60s
      -        # budget routinely interrupted legitimate work on /restart. Raise
      -        # further in config.yaml if you run very-long-reasoning models.
      -        "restart_drain_timeout": 180,
      +        # Contract: if you restart the gateway, in-flight work stops. We do
      +        # not hold the restart open for a grace window — a drain timeout
      +        # large enough to "save" a long agent turn would have to outlast an
      +        # unbounded task (some runs take days), which is impossible, and a
      +        # drain timeout shorter than systemd's TimeoutStopSec invites a
      +        # SIGKILL-mid-cleanup race that leaves a stale lock and crash-loops
      +        # the service. 0 sidesteps both: interrupt now, clean up, exit fast.
      +        # Set a positive value in config.yaml only if you explicitly want a
      +        # grace window on /restart (and keep it well under TimeoutStopSec).
      +        "restart_drain_timeout": 0,
               # Max app-level retry attempts for API errors (connection drops,
               # provider timeouts, 5xx, etc.) before the agent surfaces the
               # failure.  The OpenAI SDK already does its own low-level retries
    • tests/gateway/test_gateway_shutdown.py
      @@ -94,6 +94,10 @@ async def block_forever(_event):
       @pytest.mark.asyncio
       async def test_gateway_stop_drains_running_agents_before_disconnect():
           runner, adapter = make_restart_runner()
      +    # Opt into a grace window (the default is 0 = interrupt immediately).
      +    # This exercises the path where an agent finishes within the drain
      +    # window and must NOT be interrupted.
      +    runner._restart_drain_timeout = 5.0
           disconnect_mock = AsyncMock()
           adapter.disconnect = disconnect_mock
       

2 PRs closed without merging

From the close comments: duplicate 1 · superseded by another PR 1

  • #41525 fix(gateway): stop stale systemd timeout mismatch loop · superseded by another PR → #54066
  • #60776 fix(gateway): expand Telegram fallback IPs, fix TimeoutStopSec detection, log connection success · duplicate → #31981, #32021
Closed issues · 1
  • Closed#31981systemd TimeoutStopSec mismatch causes silent crash loop; suggested fix command is wrong
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.50: the share of item pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36. 1.00 means 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 Lab

At a glance

Subsystem
gateway
Merged PRs
#54066
Closed issues
1
Attempts
2 PRs closed without merging
Fix link checked
28 Jun 2026

For your agent

The same facts, typed.