Skip to content

Comments

fix: prevent WebSocket errors in Chrome during upload measurement#21

Open
ArtemZhyto wants to merge 1 commit intom-lab:mainfrom
ArtemZhyto:main
Open

fix: prevent WebSocket errors in Chrome during upload measurement#21
ArtemZhyto wants to merge 1 commit intom-lab:mainfrom
ArtemZhyto:main

Conversation

@ArtemZhyto
Copy link

@ArtemZhyto ArtemZhyto commented Feb 19, 2026

Description

This PR addresses the "WebSocket is already in CLOSING or CLOSED state" error that frequently occurs in Chromium-based browsers at the end of an upload test.

Changes

  • Introduced a safeSend helper function to verify sock.readyState === WebSocket.OPEN before any data transmission.
  • Added a readyState check before calling sock.close() to prevent errors when the socket is already being closed by the server or a timeout.
  • Wrapped both binary data payloads and measurement JSON strings in the safeSend guard.

Motivation

The uploader loop is scheduled via setTimeout(..., 0). In some cases, the WebSocket transitions to a CLOSING or CLOSED state between the time the timeout is scheduled and when the function actually executes. This PR ensures the client handles these transitions gracefully without throwing console errors.

Fixes #10


This change is Reviewable

@robertodauria
Copy link
Contributor

Thank you @ArtemZhyto for contributing!

This code is directly on the hot path - have you considered the performance implications? If the websocket error on Chromium is essentially benign, it may not be worth adding a conditional there. What do you think?

Copy link
Collaborator

@bassosimone bassosimone left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ArtemZhyto Hi and thank you for contributing. Questions: is the WebSocket transition of state synchronous with respect to the state of the JavaScript engine? That is, what provides us with the guarantee that after checking for the WebSocket state, the .send is not going to throw because the WebSocket was nonetheless closed? Can you elaborate on these points please? 🙏

@ArtemZhyto
Copy link
Author

ArtemZhyto commented Feb 20, 2026

Hi @robertodauria! Thanks for the catch.

You're absolutely right that this is the hot path. My reasoning for the if check was that an integer comparison (readyState === 1) is extremely lightweight in V8-significantly cheaper than the overhead of WebSocket framing or the potential cost of a try/catch block if we were to handle the error after it happens.

While the error is benign, preventing it makes the library's output much cleaner for developers and telemetry. However, if we want to prioritize maximum throughput, we could keep the check only for the close() call and the final metadata strings, leaving the main binary loop unguarded. What do you think is the better trade-off for msak-js?

@ArtemZhyto
Copy link
Author

ArtemZhyto commented Feb 20, 2026

Hi @bassosimone! Great question.

In the JavaScript environment, execution is governed by a single-threaded Event Loop. Since there is no thread preemption, the WebSocket state cannot transition during the execution of a synchronous block of code.

Once the if (sock.readyState === WebSocket.OPEN) check evaluates to true, the state is guaranteed to remain OPEN until the current function finishes and yields back to the event loop. There is no "gap" where the network stack could update the readyState property while the uploader function is still running. Therefore, the check-then-send sequence is safe from that specific type of race condition.

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.

Chrome: WebSocket error at the end of an upload measurement

3 participants