Bug Description
On macOS, hermes gateway start and hermes gateway install can fail with a CalledProcessError when launchctl bootstrap returns exit status 5 (Input/output error). This leaves the launchd service unloaded and the Telegram/Discord/WhatsApp gateway unreachable.
The root cause appears to be that launchctl bootstrap does not reliably load user LaunchAgents on newer macOS versions, especially when the job domain state is slightly out of sync. In this state, launchctl load -w succeeds immediately for the same plist file.
Environment
- OS: macOS 15.4.1 (Darwin 24.4.0, Apple Silicon)
- Python: 3.11.15
- Hermes: v0.10.0 (2026.4.16), main @
764536b6
Steps to Reproduce
- Ensure you are on macOS with a user LaunchAgent setup.
- Run
hermes gateway install or hermes gateway start.
- If
launchctl bootstrap encounters an I/O error (exit 5), the command crashes:
Installing launchd service to: /Users/<user>/Library/LaunchAgents/ai.hermes.gateway.plist
Traceback (most recent call last):
...
File "hermes_cli/gateway.py", line 1426, in launchd_install
subprocess.run(["launchctl", "bootstrap", _launchd_domain(), str(plist_path)], check=True, timeout=30)
subprocess.CalledProcessError: Command '['launchctl', 'bootstrap', 'gui/501', '/Users/.../ai.hermes.gateway.plist']' returned non-zero exit status 5.
Expected Behavior
Gateway service installation and start should be resilient to launchctl bootstrap transient failures. If bootstrap fails, Hermes should fall back to launchctl load -w <plist>, which is the traditional and more compatible way to load a user launch agent on macOS.
Actual Behavior
The CLI exits with an unhandled exception and the gateway remains down.
Proposed Fix
Wrap the three launchctl bootstrap calls in hermes_cli/gateway.py (launchd_install, launchd_start missing-plist path, and launchd_start unloaded-job path) with a try/except that falls back to:
subprocess.run(["launchctl", "load", "-w", str(plist_path)], check=True, timeout=30)
This has been verified locally to resolve the issue.
Related Issues / PRs
Bug Description
On macOS,
hermes gateway startandhermes gateway installcan fail with aCalledProcessErrorwhenlaunchctl bootstrapreturns exit status 5 (Input/output error). This leaves the launchd service unloaded and the Telegram/Discord/WhatsApp gateway unreachable.The root cause appears to be that
launchctl bootstrapdoes not reliably load user LaunchAgents on newer macOS versions, especially when the job domain state is slightly out of sync. In this state,launchctl load -wsucceeds immediately for the same plist file.Environment
764536b6Steps to Reproduce
hermes gateway installorhermes gateway start.launchctl bootstrapencounters an I/O error (exit 5), the command crashes:Expected Behavior
Gateway service installation and start should be resilient to
launchctl bootstraptransient failures. Ifbootstrapfails, Hermes should fall back tolaunchctl load -w <plist>, which is the traditional and more compatible way to load a user launch agent on macOS.Actual Behavior
The CLI exits with an unhandled exception and the gateway remains down.
Proposed Fix
Wrap the three
launchctl bootstrapcalls inhermes_cli/gateway.py(launchd_install,launchd_startmissing-plist path, andlaunchd_startunloaded-job path) with a try/except that falls back to:This has been verified locally to resolve the issue.
Related Issues / PRs
fix(launchd): --force now bootouts existing service before reinstall— addresses exit 5 during--forcereinstall, but does not add a general fallback.bootstrapI/O errors.