NousResearch/hermes-agent · error
gateway not running
Error message
gateway not running
What it means
Thrown by GatewayClient.ensureAttachedWebSocket when an RPC is attempted but this.attachUrl is unset — the client has no gateway WebSocket URL to attach to, meaning the gateway process/connection was never started (or was fully torn down). Unlike a connect failure, this is the 'nothing to connect to' case.
Source
Thrown at ui-tui/src/gatewayClient.ts:670
this.emit('event', ev)
}
if (this.pendingExit !== undefined) {
const code = this.pendingExit
this.pendingExit = undefined
this.emit('exit', code)
}
})
}
getLogTail(limit = 20): string {
return this.logs.tail(Math.max(1, limit)).join('\n')
}
private async ensureAttachedWebSocket(method: string): Promise<WebSocket> {
if (!this.attachUrl) {
throw new Error('gateway not running')
}
if (!this.ws || this.ws.readyState === WS_CLOSED || this.ws.readyState === WS_CLOSING) {
this.start()
}
if (this.ws?.readyState === WS_CONNECTING) {
try {
await this.wsConnectPromise
} catch (err) {
throw err instanceof Error ? err : new Error(String(err))
}
}
if (!this.ws || this.ws.readyState !== WS_OPEN) {
throw new Error(`gateway not connected: ${method}`)
}
View on GitHub (pinned to c896c09c42)
Solutions
- Ensure the gateway is started/connected (await the client's ready/connect event) before issuing RPCs.
- If using an external gateway, verify its URL is configured so attachUrl gets set at construction.
- Gate UI actions that need the gateway on connection state; re-establish after an exit event.
Example fix
// before
const res = await client.rpc('session.list')
// after
await client.whenReady?.() // or start()/connect first
const res = await client.rpc('session.list') Defensive patterns
Strategy: type-guard
Validate before calling
function hasAttachUrl(client: GatewayClient): boolean {
return Boolean((client as unknown as { attachUrl?: string }).attachUrl)
} Type guard
function isAttached(client: GatewayClient): boolean {
return client.attachUrl !== undefined && client.ws?.readyState === WebSocket.OPEN
} Try / catch
try {
await client.rpc('session.list')
} catch (e) {
if (e instanceof Error && e.message === 'gateway not running') {
await client.start(); await ready
return client.rpc('session.list')
}
throw e
} Prevention
- Await the client's ready/connect lifecycle before issuing any RPC.
- Configure the gateway URL up front when using an external gateway.
- Disable gateway-dependent UI until connection state is established.
When it happens
Trigger: Calling gateway.rpc(...) / requestOverWebSocket before start() established attachUrl, or after stop()/exit cleared it; also when the TUI launches without spawning/connecting to a gateway (misconfigured remote mode).
Common situations: TUI startup race where a component issues an RPC before gateway ready, using --no-spawn/remote flags without a gateway URL configured, or issuing requests after the gateway exited.
Related errors
- gateway not connected: ${method}
- Gateway did not return a WS ticket.
- Remote Hermes gateway is selected, but no session token is s
- Reached the gateway over HTTP, but the live WebSocket (/api/
- Hermes backend for profile "${profile}" is HTTP-reachable bu
AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14).
Data as JSON: /api/errors/9b54e75f74b37c9f.
Report an issue: GitHub.