paperclipai/paperclip · error · Error
gateway not connected
Error message
gateway not connected
What it means
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.
Source
Thrown at packages/adapters/openclaw-gateway/src/server/execute.ts:712
);
const nonce = await withTimeout(this.challengePromise, timeoutMs, "gateway connect challenge timeout");
const signedConnectParams = buildConnectParams(nonce);
const hello = await this.request<Record<string, unknown> | null>("connect", signedConnectParams, {
timeoutMs,
});
return hello;
}
async request<T>(
method: string,
params: unknown,
opts: GatewayClientRequestOptions,
): Promise<T> {
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
throw new Error("gateway not connected");
}
const id = randomUUID();
const frame: GatewayRequestFrame = {
type: "req",
id,
method,
params,
};
const payload = JSON.stringify(frame);
const requestPromise = new Promise<T>((resolve, reject) => {
const timer =
opts.timeoutMs > 0
? setTimeout(() => {
this.pending.delete(id);
reject(new Error(`gateway request timeout (${method})`));
}, opts.timeoutMs)View on GitHub (pinned to 67001ec6eb)
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.
Example fix
// before
const client = new GatewayClient(opts);
await client.request("run", params, { timeoutMs: 5000 }); // throws: not connected
// after
await client.connect(buildConnectParams, 5000);
await client.request("run", params, { timeoutMs: 5000 }); Defensive patterns
Strategy: try-catch
Validate before calling
function isGatewayReady(client: { ws: WebSocket | null }): boolean {
return client.ws != null && client.ws.readyState === WebSocket.OPEN;
}
// guard before request
if (!isGatewayReady(client)) { await client.connect(buildConnectParams, 5000); } Type guard
function isGatewayConnected(client: { ws: WebSocket | null }): client is { ws: WebSocket & { readyState: typeof WebSocket.OPEN } } {
return client.ws != null && client.ws.readyState === WebSocket.OPEN;
} Try / catch
async function requestWithReconnect<T>(client: GatewayClient, method: string, params: unknown, opts: GatewayClientRequestOptions): Promise<T> {
try {
return await client.request<T>(method, params, opts);
} catch (e) {
if (e instanceof Error && /gateway not connected/.test(e.message)) {
await client.connect(buildConnectParams, opts.timeoutMs);
return client.request<T>(method, params, opts);
}
throw e;
}
} Prevention
- 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.
When it happens
Trigger: 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().
Common situations: 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().
Related errors
- Request failed: ${response.status}
- Request failed with status ${response.status}
- Export request returned no data
- The Paperclip database is not running or reachable, so the p
- Failed to fetch from remote "${remote}": ${extractExecSyncEr
AI-assisted analysis of paperclipai/paperclip@67001ec6eb (2026-08-12).
Data as JSON: /api/errors/28426cf11969fe5f.
Report an issue: GitHub.