NousResearch/hermes-agent · error · Error
Local Hermes backend is HTTP-reachable but the WebSocket (/a
Error message
Local Hermes backend is HTTP-reachable but the WebSocket (/api/ws) rejected the session token: ${wsProbe.reason} What it means
Local-boot path variant of the WS token verification: the locally started Hermes backend (dashboard/serve child) answered HTTP, adoptServedDashboardToken obtained the session token from the child, but the subsequent WebSocket probe to ws://127.0.0.1:<port>/api/ws?token=... was rejected. Boot aborts at ~progress-94 stage because the real app transport (WS) cannot authenticate even though REST works. It almost always indicates token mismatch between the spawned child and the probe, or an unexpected process on the port.
Source
Thrown at apps/desktop/electron/main.ts:8614
}
const baseUrl = `http://127.0.0.1:${port}`
await advanceBootProgress('backend.wait', 'Waiting for Hermes backend to become ready', 90)
await Promise.race([waitForHermes(baseUrl, token), backendStartFailed])
backendReady = true
backendStartFailure = null
const authToken = await adoptServedDashboardToken(baseUrl, token, {
childAlive: () => hermesProcess.exitCode === null && !hermesProcess.killed,
rememberLog
})
// Verify the WebSocket session token before declaring backend ready.
const wsUrl = `ws://127.0.0.1:${port}/api/ws?token=${encodeURIComponent(authToken)}`
const wsProbe = await probeGatewayWebSocket(wsUrl, { WebSocketImpl: globalThis.WebSocket })
if (!wsProbe.ok) {
throw new Error(
`Local Hermes backend is HTTP-reachable but the WebSocket (/api/ws) rejected the session token: ${wsProbe.reason}`
)
}
updateBootProgress({
phase: 'backend.ready',
message: 'Hermes backend is ready. Finalizing desktop startup',
progress: 94,
running: true,
error: null
})
// A successful boot (including a soft restart that the repair-guard
// chose over a hard reinstall, see #74874) means any in-flight repair
// attempt counter has been honoured — reset it so the next genuine
// failure starts fresh from attempt 1 instead of inheriting the
// accumulated count of the resolved episode.
bootstrapRepairAttempt = 0View on GitHub (pinned to c896c09c42)
Solutions
- Inspect wsProbe.reason in the thrown message for 401/403 vs connection-closed
- Kill orphan hermes serve/dashboard processes (pgrep -af 'hermes (serve|dashboard)') and retry boot
- Reinstall/align the managed hermes runtime with the desktop app version
- Check the child's captured logs (rememberLog output surfaced in boot diagnostics) for auth errors on /api/ws
- Retry once after a clean disconnect; transient adoption-vs-readiness races resolve on a fresh boot
Defensive patterns
Strategy: retry
Type guard
function isLocalWsAuthFailure(e: unknown): boolean {
return e instanceof Error && e.message.startsWith('Local Hermes backend is HTTP-reachable but the WebSocket')
} Try / catch
try { await startLocalBackend() } catch (e) { if (isLocalWsAuthFailure(e)) { await cleanupOrphanBackends(); await startLocalBackend() } else throw e } Prevention
- Quit the desktop app cleanly so locally spawned backends exit with it
- After app updates, verify no orphan 'hermes serve' processes hold the port
- Read wsProbe.reason: 401/403 points to token/version mismatch, closed points to a dying child
When it happens
Trigger: probeGatewayWebSocket on the adopted dashboard token fails: token rejected during WS upgrade (401/403), the adopted token belongs to a different (stale) process on the same port, or the child died between the HTTP adoption and the WS probe.
Common situations: Leftover 'hermes dashboard'/'hermes serve' process from a crashed prior session occupying the port; mixed versions after an app update (runtime adopts one token scheme, desktop probes another); very fast machines/timing windows where the child rotates tokens at readiness.
Related errors
- Hermes backend for profile "${profile}" is HTTP-reachable bu
- Gateway did not return a WS ticket.
- Remote gateway session token is required.
- Remote Hermes gateway is selected, but no session token is s
- 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/2193b1467e7e79cb.
Report an issue: GitHub.