Skip to content

WebSocketFactory.reconnect() never executes due to truthy sentinel value #323

Description

@christianvogt

Description

The reconnect() method in WebSocketFactory is unreachable due to a JavaScript truthiness bug with the connectionAttempt sentinel value. Even when reconnect: true is passed in options, websocket connections that are closed by the server are never automatically re-established.

The Bug

connectionAttempt is initialized to -1 as a sentinel meaning "no active reconnect timer":

private connectionAttempt = -1;

The reconnect() method guards against duplicate reconnect attempts:

private async reconnect(): Promise<void> {
  if (this.connectionAttempt || this.state === WebSocketState.DESTROYED) {
    return;
  }
  // ... reconnect logic ...
}

In JavaScript, -1 is truthy. This guard always evaluates to true, so reconnect() returns immediately without ever reaching the reconnection logic — including the check for this.options.reconnect.

The onclose handler calls this.reconnect(), and onopen resets connectionAttempt back to -1. So every close/reconnect cycle hits the same dead path.

Impact

Any consumer using WebSocketFactory with { reconnect: true } (including k8sWatch in @openshift/dynamic-plugin-sdk-utils, which sets this as a default) will never recover from a server-side close. The websocket silently dies and is never re-established. Consumers relying on watch semantics for real-time updates will stop receiving events permanently until the user triggers a full page reload or re-navigation.

Suggested Fix

Option A — Change the sentinel to a falsy value (recommended):

Replace all occurrences of this.connectionAttempt = -1 with this.connectionAttempt = 0, and update the initializer:

private connectionAttempt = 0;

0 is falsy in JavaScript and is never returned by window.setTimeout (which returns positive integers), making it a correct sentinel for "no active timer."

Option B — Use an explicit comparison in the guard:

if (this.connectionAttempt > 0 || this.state === WebSocketState.DESTROYED) {

Affected File

packages/lib-utils/src/web-socket/WebSocketFactory.ts

Version

Confirmed in @openshift/dynamic-plugin-sdk@5.0.1 / @openshift/dynamic-plugin-sdk-utils@5.0.1. The bug appears to be present on main as well based on the current source.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions