NousResearch/hermes-agent · error

gateway not connected

Error message

gateway not connected: ${method}

What it means

Thrown by GatewayClient.ensureAttachedWebSocket after it attempted (re)connection: attachUrl exists, start() was called if needed, the CONNECTING promise was awaited, but the WebSocket still is not in OPEN state — the connection attempt failed, closed immediately, or is stuck. The method name is included to identify which RPC was blocked.

Solutions

  1. Verify the gateway is actually running and listening on the configured URL/port.
  2. Check gateway logs for handshake/auth failures; fix credentials if the socket is closed on auth.
  3. Retry after the gateway reports ready; add backoff/retry around RPCs issued during startup.
  4. Confirm no proxy in between strips WebSocket upgrades (wss/WS upgrade headers).
Defensive patterns

Strategy: retry

Validate before calling

function wsOpen(client: GatewayClient): boolean {
  return client.ws?.readyState === WebSocket.OPEN
}

// issue RPCs only when wsOpen(client) is true, or after the ready event

Type guard

function isWsOpen(ws: WebSocket | undefined): ws is WebSocket {
  return ws !== undefined && ws.readyState === WebSocket.OPEN
}

Try / catch

try {
  await client.rpc(method, params)
} catch (e) {
  if (e instanceof Error && e.message.startsWith('gateway not connected')) {
    await backoff(500)
    return client.rpc(method, params) // single retry after reconnect
  }
  throw e
}

Prevention

When it happens

Trigger: Any gateway.rpc(...) while the WebSocket handshake fails: backend not listening on the port/URL, auth rejection closing the socket, network unreachable, or the socket closing between the connect-await and the state check.

Common situations: Gateway process crashed or still booting when the TUI connects, wrong port/URL in config, firewall/proxy blocking WS upgrade, or token auth failing so the server closes the connection instantly.

Related errors


AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14). Data as JSON: /api/errors/eee3a62ea3e0261d. Report an issue: GitHub.

Appendix: source

Thrown at ui-tui/src/gatewayClient.ts:686

  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}`)
    }

    return this.ws
  }

  private requestOverWebSocket<T = unknown>(method: string, params: Record<string, unknown> = {}): Promise<T> {
    return this.ensureAttachedWebSocket(method).then(
      ws =>
        new Promise<T>((resolve, reject) => {
          const id = `r${++this.reqId}`
          const timeout = setTimeout(this.onTimeout, REQUEST_TIMEOUT_MS, id)

          timeout.unref?.()
          this.pending.set(id, {
            id,
            method,
            reject,
            resolve: v => resolve(v as T),

View on GitHub (pinned to c896c09c42)