NousResearch/hermes-agent · error
Gateway restart failed.
Error message
Gateway restart failed.
What it means
Thrown by awaitAction() inside the gateway-restart flow when the polled backend action (messaging gateway restart) finishes with a non-zero exit code. The action is started via a backend command, then polled with getActionStatus; a completed-but-failed process (exit_code != 0) surfaces as this localized 'Gateway restart failed.' error so the caller (runGatewayRestart, which never rejects) can toast the failure.
Source
Thrown at apps/desktop/src/store/system-actions.ts:26
const POLL_ATTEMPTS = 18
const POLL_INTERVAL_MS = 1200
const POLL_TIMEOUT_S = 180
// True while a gateway restart is in flight — drives the statusbar gateway
// indicator (glyph spinner) so the restart shows up where users already look,
// instead of a toast that vanishes or a generic "Agents running" counter.
export const $gatewayRestarting = atom(false)
// Poll a backend action to completion (or a bounded window), throwing on a
// non-zero exit so the caller can surface the failure.
async function awaitAction(started: ActionResponse): Promise<void> {
for (let attempt = 0; attempt < POLL_ATTEMPTS; attempt += 1) {
await new Promise(resolve => window.setTimeout(resolve, POLL_INTERVAL_MS))
const status = await getActionStatus(started.name, POLL_TIMEOUT_S)
if (!status.running) {
if (status.exit_code != null && status.exit_code !== 0) {
throw new Error(translateNow('commandCenter.gatewayRestartFailed'))
}
return
}
}
}
// Restart the messaging gateway, surfacing progress in the statusbar gateway
// indicator. Self-contained and never rejects, so every trigger — Cmd+K, the
// messaging save/toggle toasts — gets identical feedback from a plain
// `void runGatewayRestart()`, and a failure is the only thing that toasts.
export async function runGatewayRestart(): Promise<void> {
$gatewayRestarting.set(true)
try {
await awaitAction(await restartGateway())
} catch (err) {
notifyError(err, translateNow('commandCenter.gatewayRestartFailed'))View on GitHub (pinned to c896c09c42)
Solutions
- Inspect the backend gateway logs (~/.hermes/logs/gateway.log or the errors log) for the actual exit reason.
- Check for a stale gateway process holding the port (ps / lsof) and kill it, then restart again.
- Validate the gateway config/credentials just saved (settings -> messaging) — a bad token or YAML makes the restart script fail.
- Retry via Settings -> Gateway restart after fixing the root cause; if the action status itself was unobservable, verify the backend action runner is alive.
Defensive patterns
Strategy: try-catch
Try / catch
try {
await runGatewayRestart() // never rejects; check its toast
} catch { /* not expected; kept for safety */ }
// lower level:
try { await awaitAction(started) } catch (e) { surface(getActionLogTail(started.name)) } Prevention
- Before restarting, verify gateway config parses and the port is free.
- Keep gateway logs open when changing messaging settings that trigger auto-restart.
- Treat non-zero exit as actionable: read gateway.log, do not blind-retry.
When it happens
Trigger: runGatewayRestart() (Cmd+K command, or the messaging settings save/toggle path) starts a gateway restart action; the backend's restart script/process exits non-zero — port already in use, config parse error in gateway config, missing token, or the old gateway failing to stop.
Common situations: Gateway port conflict from a previous instance still bound, an invalid gateway platform credential edited in settings, or a config.yaml syntax error introduced by a settings save right before the restart.
Related errors
- Gateway did not return a WS ticket.
- Remote gateway session token is required.
- Remote Hermes gateway is selected, but no session token is s
- HERMES_DESKTOP_REMOTE_URL is set but HERMES_DESKTOP_REMOTE_T
- Reached the gateway over HTTP, but the live WebSocket (/api/
AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14).
Data as JSON: /api/errors/0c018b20a727c791.
Report an issue: GitHub.