ruvnet/ruflo · error

Client heartbeat timeout

Error message

Client heartbeat timeout

What it means

The heartbeat interval found a client whose isAlive flag was still false after the last ping — it never sent a pong within heartbeatTimeout. The server logs the timeout and disconnects the dead client (standard WS liveness reaping), freeing its connection slot.

Source

Thrown at v3/mcp/transport/websocket.ts:478

    if (this.config.enableBinaryMode) {
      // Could implement binary protocol here
      return JSON.stringify(message);
    }
    return JSON.stringify(message);
  }

  /**
   * Start heartbeat interval
   */
  private startHeartbeat(): void {
    const interval = this.config.heartbeatInterval || 30000; // 30 seconds
    const timeout = this.config.heartbeatTimeout || 10000; // 10 seconds

    this.heartbeatTimer = setInterval(() => {
      for (const client of this.clients.values()) {
        if (!client.isAlive) {
          // Client didn't respond to last ping
          this.logger.warn('Client heartbeat timeout', { id: client.id });
          client.ws.terminate();
          this.clients.delete(client.id);
          continue;
        }

        client.isAlive = false;
        try {
          client.ws.ping();
        } catch {
          // Ignore ping errors
        }
      }
    }, interval);
  }

  /**
   * Stop heartbeat interval
   */

View on GitHub (pinned to fa13ee4ad6)

Solutions

  1. Verify the client sends heartbeat/ping frames within the configured interval.
  2. Increase the heartbeat timeout for high-latency clients.
  3. Check for client-side event-loop stalls delaying heartbeats, and ensure reconnect logic recovers the socket.
Defensive patterns

Strategy: retry

When it happens

Trigger: WebSocket client fails to respond to heartbeat pings within the timeout; dead peer, suspended browser tab, or broken network path; server closes and cleans up the connection.

Common situations: See trigger scenarios.

Understand the failure class


AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18). Data as JSON: /api/errors/cd1443a6fd684e19. Report an issue: GitHub.