{"record":{"id":"9b54e75f74b37c9f","repo":"NousResearch/hermes-agent","slug":"gateway-not-running","errorCode":null,"errorMessage":"gateway not running","messagePattern":"gateway not running","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"ui-tui/src/gatewayClient.ts","lineNumber":670,"sourceCode":"        this.emit('event', ev)\n      }\n\n      if (this.pendingExit !== undefined) {\n        const code = this.pendingExit\n\n        this.pendingExit = undefined\n        this.emit('exit', code)\n      }\n    })\n  }\n\n  getLogTail(limit = 20): string {\n    return this.logs.tail(Math.max(1, limit)).join('\\n')\n  }\n\n  private async ensureAttachedWebSocket(method: string): Promise<WebSocket> {\n    if (!this.attachUrl) {\n      throw new Error('gateway not running')\n    }\n\n    if (!this.ws || this.ws.readyState === WS_CLOSED || this.ws.readyState === WS_CLOSING) {\n      this.start()\n    }\n\n    if (this.ws?.readyState === WS_CONNECTING) {\n      try {\n        await this.wsConnectPromise\n      } catch (err) {\n        throw err instanceof Error ? err : new Error(String(err))\n      }\n    }\n\n    if (!this.ws || this.ws.readyState !== WS_OPEN) {\n      throw new Error(`gateway not connected: ${method}`)\n    }\n","sourceCodeStart":652,"sourceCodeEnd":688,"githubUrl":"https://github.com/NousResearch/hermes-agent/blob/c896c09c42910c584c4c7d2325b58c14713ea42c/ui-tui/src/gatewayClient.ts#L652-L688","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":"// before\nconst res = await client.rpc('session.list')\n\n// after\nawait client.whenReady?.() // or start()/connect first\nconst res = await client.rpc('session.list')","handlingStrategy":"type-guard","validationCode":"function hasAttachUrl(client: GatewayClient): boolean {\n  return Boolean((client as unknown as { attachUrl?: string }).attachUrl)\n}","typeGuard":"function isAttached(client: GatewayClient): boolean {\n  return client.attachUrl !== undefined && client.ws?.readyState === WebSocket.OPEN\n}","tryCatchPattern":"try {\n  await client.rpc('session.list')\n} catch (e) {\n  if (e instanceof Error && e.message === 'gateway not running') {\n    await client.start(); await ready\n    return client.rpc('session.list')\n  }\n  throw e\n}","preventionTips":["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."],"tags":["tui","gateway","websocket","connection","startup-race"],"backgroundTag":null,"analyzedSha":"c896c09c42910c584c4c7d2325b58c14713ea42c","analyzedAt":"2026-08-14T17:18:01.089Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}