openclaw - 💡(How to fix) Fix WebSocket handshake timeout (3000ms) causes CLI commands to fail intermittently [3 comments, 3 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#48954Fetched 2026-04-08 00:50:34
View on GitHub
Comments
3
Participants
3
Timeline
3
Reactions
0
Timeline (top)
commented ×3

Error Message

[openclaw] Failed to start CLI: Error: gateway closed (1000 normal closure): no close reason Gateway target: ws://127.0.0.1:18789

Root Cause

When executing CLI commands like openclaw devices list or openclaw logs, the WebSocket handshake frequently times out with error code 1000 (normal closure). The TUI works because it has retry logic, but short-lived CLI commands fail.

Fix Action

Fix / Workaround

Workaround

Code Example

[openclaw] Failed to start CLI: Error: gateway closed (1000 normal closure): no close reason
Gateway target: ws://127.0.0.1:18789

---

{"cause":"handshake-timeout","handshake":"failed","durationMs":3569,"handshakeMs":3001}
RAW_BUFFERClick to expand / collapse

Description

When executing CLI commands like openclaw devices list or openclaw logs, the WebSocket handshake frequently times out with error code 1000 (normal closure). The TUI works because it has retry logic, but short-lived CLI commands fail.

Environment

  • OpenClaw version: 2026.3.13
  • OS: macOS Darwin 24.6.0
  • Node.js: v24.14.0 (via nvm)

Observed Behavior

[openclaw] Failed to start CLI: Error: gateway closed (1000 normal closure): no close reason
Gateway target: ws://127.0.0.1:18789

Gateway logs show:

{"cause":"handshake-timeout","handshake":"failed","durationMs":3569,"handshakeMs":3001}

Analysis

  1. WebSocket handshake timeout is hardcoded to 3000ms
  2. Actual handshake time varies: 2000-3500ms (unstable)
  3. When handshake exceeds 3000ms, Gateway closes connection
  4. TUI succeeds because it retries; CLI fails immediately

System checks (all normal):

  • System load: 2.86 (multi-core, acceptable)
  • DNS resolution: 49ms
  • HTTP requests: 20ms
  • Node.js startup: 65ms

Root Cause

Gateway internal implementation issue:

  • Handshake time is unstable (varies 2000-3500ms)
  • 3000ms timeout is hardcoded, not configurable
  • Cannot be resolved through configuration or external optimization

Proposed Solutions

  1. Make WebSocket handshake timeout configurable (e.g., gateway.wsHandshakeTimeoutMs)
  2. Increase default timeout to 10000ms
  3. Optimize handshake flow performance
  4. Add automatic retry mechanism to CLI commands

Workaround

  • Use openclaw tui instead of short CLI commands
  • TUI has retry logic and eventually succeeds

Related

Issue was initially thought to be plugin-related, but further analysis confirmed it is a Gateway handshake performance issue. Plugin loading does not occur on each CLI connection - the logs shown are CLI initialization output, not Gateway responses.


Reported by: piggy-weihaostudio (OpenClaw user)

extent analysis

Fix Plan

To resolve the WebSocket handshake timeout issue, we will implement the following steps:

  • Make the WebSocket handshake timeout configurable
  • Increase the default timeout to 10000ms
  • Add an automatic retry mechanism to CLI commands

Step 1: Make WebSocket Handshake Timeout Configurable

We will introduce a new configuration option gateway.wsHandshakeTimeoutMs to allow users to adjust the timeout value.

// config.js
const config = {
  // ...
  gateway: {
    wsHandshakeTimeoutMs: 10000, // default value
  },
};

Step 2: Increase Default Timeout

We will update the default timeout value to 10000ms in the Gateway implementation.

// gateway.js
const wsHandshakeTimeoutMs = config.gateway.wsHandshakeTimeoutMs || 10000;

Step 3: Add Automatic Retry Mechanism to CLI Commands

We will implement a retry mechanism with a maximum of 3 attempts and a 500ms delay between attempts.

// cli.js
const maxRetries = 3;
const retryDelayMs = 500;

async function executeCliCommand() {
  let retries = 0;
  while (retries < maxRetries) {
    try {
      // execute CLI command
      return;
    } catch (error) {
      if (error.code === 1000) {
        retries++;
        await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
      } else {
        throw error;
      }
    }
  }
  throw new Error(`Failed to execute CLI command after ${maxRetries} retries`);
}

Verification

To verify that the fix worked, run the following CLI commands and check for successful execution:

  • openclaw devices list
  • openclaw logs

Monitor the Gateway logs to ensure that the handshake timeout errors are resolved.

Extra Tips

  • Consider optimizing the handshake flow performance to reduce the timeout value.
  • Review the plugin loading process to ensure it does not contribute to the handshake timeout issue.
  • Test the retry mechanism with different timeout values to ensure it works as expected.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING