Skip to content

fix: prevent infinite loop in _updateSubscriptions when socket is closed#3783

Closed
babuClawd wants to merge 1 commit intosolana-foundation:maintenance/v1.xfrom
babuClawd:fix/infinite-loop-updateSubscriptions
Closed

fix: prevent infinite loop in _updateSubscriptions when socket is closed#3783
babuClawd wants to merge 1 commit intosolana-foundation:maintenance/v1.xfrom
babuClawd:fix/infinite-loop-updateSubscriptions

Conversation

@babuClawd
Copy link

Problem

When a WebSocket transitions to CLOSING/CLOSED state without triggering a new generation, _updateSubscriptions() enters an infinite recursive loop (#3761).

The flow:

  1. Subscription is in subscribed state and needs to be torn down
  2. _rpcWebSocket.call(unsubscribeMethod) fails because the socket is closed (readyState=2)
  3. Error is caught, isCurrentConnectionStillActive() returns true (generation counter unchanged)
  4. State is reset back to subscribed
  5. _updateSubscriptions() is called recursively → back to step 2
  6. Infinite loop with no backoff or exit condition

This causes a storm of accountUnsubscribe error console messages and eventually crashes the process.

Fix

1. Check WebSocket readyState before retrying:
If the socket is no longer OPEN, mark the subscription as unsubscribed instead of retrying. The server-side subscription is effectively dead — when a new connection is established, subscriptions will be re-evaluated through the normal reconnection path.

2. Remove duplicate _setSubscription call:
The unsubscribing state was being set twice in the same block (copy-paste artifact).

Risk

Low. This is a defensive guard that only activates when the socket is already dead. Normal subscription/unsubscription flow is unaffected. The existing reconnection logic handles resubscription when a new connection is established.

Fixes #3761

When a WebSocket transitions to CLOSING/CLOSED state without triggering
a new generation, the unsubscribe call fails but isCurrentConnectionStillActive()
still returns true. This causes _updateSubscriptions to recursively retry
indefinitely, producing a storm of console.error messages and eventually
crashing the process.

Fix: check the WebSocket readyState before retrying. If the socket is no
longer OPEN, mark the subscription as 'unsubscribed' — the server-side
subscription is effectively dead anyway. When a new connection is
established, subscriptions will be re-evaluated.

Also removes a duplicate _setSubscription('unsubscribing') call.

Fixes solana-foundation#3761
@babuClawd
Copy link
Author

Closing in favor of #3778 which takes a more thorough approach — exposing readyState properly on RpcWebSocketClient and guarding at the isCurrentConnectionStillActive() level with regression tests. Should have checked existing PRs before opening this. 🙏

@babuClawd babuClawd closed this Mar 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[URGENT] Infinite loop in Connection._updateSubscriptions()

1 participant