Bug Description
When launching hermes desktop, the in-app auto-update mechanism (applyUpdatesPosixInApp) runs hermes update, which calls _kill_stale_dashboard_processes(). That function scans the process table for anything matching hermes dashboard and sends SIGTERM — including the hermes dashboard process that the Electron app itself spawned as its backend.
This creates a boot→kill→reboot→crash loop where the desktop can never stay connected.
Steps to Reproduce
- Be 1+ commits behind origin/main
- Run
hermes desktop
- Desktop spawns
hermes dashboard --no-open --tui --host 127.0.0.1 --port <random> as its backend
- Backend becomes ready, desktop connects successfully
- Desktop renderer detects pending updates and triggers
hermes:updates:apply
applyUpdatesPosixInApp runs hermes update --yes
hermes update calls _kill_stale_dashboard_processes() which SIGTERMs the desktop's own backend
- Desktop detects backend died, restarts it
- Update rebuilds the desktop app, triggering another restart
- Final backend starts but then crashes:
⚡ Interrupted during API call
- All subsequent
hermes:api IPC calls timeout: Error: Timed out connecting to Hermes backend after 15000ms
Root Cause
_find_stale_dashboard_pids() in hermes_cli/main.py (line ~7131) only exempts its own PID:
if any(p in command for p in patterns) and pid != self_pid:
dashboard_pids.append(pid)
It does not account for the case where hermes update was invoked by the Electron desktop app, whose child hermes dashboard process should NOT be killed.
Desktop Log Evidence
[hermes] [boot] Hermes backend is ready. Finalizing desktop startup
[hermes] [updates] update: Updating Hermes (git + dependencies)…
... (update runs) ...
[hermes] Hermes backend exited (SIGTERM)
[hermes] Hermes backend exited (SIGTERM)
[hermes] [updates] update: ⟲ Stopping 2 dashboard process(es) (the running backend no longer matches the updated frontend)
[hermes] [updates] update: ✓ stopped PID 717447
[hermes] [updates] update: ✓ stopped PID 717805
... (rebuild happens, desktop reboots) ...
[hermes] [boot] Hermes backend is ready. Finalizing desktop startup
[hermes] ⚡ Interrupted during API call.
After this, every IPC call from the renderer fails with:
Error occurred in handler for 'hermes:api': Error: Timed out connecting to Hermes backend after 15000ms
Suggested Fix
Any of:
- Exclusion PID list:
_find_stale_dashboard_pids() accepts an optional exclude_pids parameter. The desktop passes its backend child PID.
- Env var marker: The desktop sets
HERMES_DESKTOP_MANAGED=1 on its spawned backend process. _find_stale_dashboard_pids() skips processes with that env var.
- Desktop handles post-update restart: Instead of having
hermes update kill dashboards, the desktop kills its own backend after the update completes and restarts it cleanly.
Environment
- Hermes v0.15.1
- Linux 7.0.10-201.fc44.x86_64 (Aurora/Fedora immutable)
- Electron 40.9.3
- Python 3.11.14
Workaround
Run hermes update separately before launching the desktop, so the auto-update has nothing to trigger on:
hermes update --yes
hermes desktop
Bug Description
When launching
hermes desktop, the in-app auto-update mechanism (applyUpdatesPosixInApp) runshermes update, which calls_kill_stale_dashboard_processes(). That function scans the process table for anything matchinghermes dashboardand sends SIGTERM — including thehermes dashboardprocess that the Electron app itself spawned as its backend.This creates a boot→kill→reboot→crash loop where the desktop can never stay connected.
Steps to Reproduce
hermes desktophermes dashboard --no-open --tui --host 127.0.0.1 --port <random>as its backendhermes:updates:applyapplyUpdatesPosixInApprunshermes update --yeshermes updatecalls_kill_stale_dashboard_processes()which SIGTERMs the desktop's own backend⚡ Interrupted during API callhermes:apiIPC calls timeout:Error: Timed out connecting to Hermes backend after 15000msRoot Cause
_find_stale_dashboard_pids()inhermes_cli/main.py(line ~7131) only exempts its own PID:It does not account for the case where
hermes updatewas invoked by the Electron desktop app, whose childhermes dashboardprocess should NOT be killed.Desktop Log Evidence
After this, every IPC call from the renderer fails with:
Suggested Fix
Any of:
_find_stale_dashboard_pids()accepts an optionalexclude_pidsparameter. The desktop passes its backend child PID.HERMES_DESKTOP_MANAGED=1on its spawned backend process._find_stale_dashboard_pids()skips processes with that env var.hermes updatekill dashboards, the desktop kills its own backend after the update completes and restarts it cleanly.Environment
Workaround
Run
hermes updateseparately before launching the desktop, so the auto-update has nothing to trigger on: