{"record":{"id":"28426cf11969fe5f","repo":"paperclipai/paperclip","slug":"gateway-not-connected","errorCode":null,"errorMessage":"gateway not connected","messagePattern":"gateway not connected","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/adapters/openclaw-gateway/src/server/execute.ts","lineNumber":712,"sourceCode":"    );\n\n    const nonce = await withTimeout(this.challengePromise, timeoutMs, \"gateway connect challenge timeout\");\n    const signedConnectParams = buildConnectParams(nonce);\n\n    const hello = await this.request<Record<string, unknown> | null>(\"connect\", signedConnectParams, {\n      timeoutMs,\n    });\n\n    return hello;\n  }\n\n  async request<T>(\n    method: string,\n    params: unknown,\n    opts: GatewayClientRequestOptions,\n  ): Promise<T> {\n    if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {\n      throw new Error(\"gateway not connected\");\n    }\n\n    const id = randomUUID();\n    const frame: GatewayRequestFrame = {\n      type: \"req\",\n      id,\n      method,\n      params,\n    };\n\n    const payload = JSON.stringify(frame);\n    const requestPromise = new Promise<T>((resolve, reject) => {\n      const timer =\n        opts.timeoutMs > 0\n          ? setTimeout(() => {\n              this.pending.delete(id);\n              reject(new Error(`gateway request timeout (${method})`));\n            }, opts.timeoutMs)","sourceCodeStart":694,"sourceCodeEnd":730,"githubUrl":"https://github.com/paperclipai/paperclip/blob/67001ec6eb96ae601aa27bc91d9b2415d665334a/packages/adapters/openclaw-gateway/src/server/execute.ts#L694-L730","documentation":"Thrown by GatewayClient.request (openclaw-gateway) when a JSON-RPC request frame is attempted but the underlying WebSocket is missing or not in the OPEN state. The client requires connect() to complete (WS open + challenge + connect handshake) before any request(), so this guards against use-before-connect and use-after-close.","triggerScenarios":"request() is called before connect() resolves; request() is called after the WS emitted close/error (this.ws set to null by close() or never reassigned); a race where the server closed the socket between the readyState check and ws.send().","commonSituations":"Caller forgets to await connect(); the gateway dropped the connection (network blip, server restart) and the caller did not register a close handler to reconnect; concurrent close() racing a request().","solutions":["Always await client.connect(buildConnectParams, timeoutMs) before issuing any request().","Register for the WS close/error events (or wrap the client) and reconnect before retrying the request.","Guard the call site: check the client is connected, or implement a reconnect-then-request wrapper with a short timeout.","Avoid calling close() concurrently with in-flight requests; drain pending requests first."],"exampleFix":"// before\nconst client = new GatewayClient(opts);\nawait client.request(\"run\", params, { timeoutMs: 5000 }); // throws: not connected\n// after\nawait client.connect(buildConnectParams, 5000);\nawait client.request(\"run\", params, { timeoutMs: 5000 });","handlingStrategy":"try-catch","validationCode":"function isGatewayReady(client: { ws: WebSocket | null }): boolean {\n  return client.ws != null && client.ws.readyState === WebSocket.OPEN;\n}\n// guard before request\nif (!isGatewayReady(client)) { await client.connect(buildConnectParams, 5000); }","typeGuard":"function isGatewayConnected(client: { ws: WebSocket | null }): client is { ws: WebSocket & { readyState: typeof WebSocket.OPEN } } {\n  return client.ws != null && client.ws.readyState === WebSocket.OPEN;\n}","tryCatchPattern":"async function requestWithReconnect<T>(client: GatewayClient, method: string, params: unknown, opts: GatewayClientRequestOptions): Promise<T> {\n  try {\n    return await client.request<T>(method, params, opts);\n  } catch (e) {\n    if (e instanceof Error && /gateway not connected/.test(e.message)) {\n      await client.connect(buildConnectParams, opts.timeoutMs);\n      return client.request<T>(method, params, opts);\n    }\n    throw e;\n  }\n}","preventionTips":["Always await connect() before any request().","Subscribe to WS close/error and reconnect proactively, not on next request.","Never call close() while requests are in-flight; drain first."],"tags":["gateway","websocket","openclaw","connection-lifecycle","network"],"backgroundTag":null,"analyzedSha":"67001ec6eb96ae601aa27bc91d9b2415d665334a","analyzedAt":"2026-08-12T12:05:45.408Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}