Skip to content

ws >= 7.5.11 default frame limits silently kill the CDP connection: "WebSocket connection closed", run hangs on a blank page #8546

Description

@Gash003

What is your Scenario?

Run any sufficiently large test suite with native automation (Chrome). Our suite has ~88 tests against a payload-heavy SPA.

What is the Current behavior?

Since ws 7.5.12 got resolved into our lockfile (Dependabot bump; any fresh npm install of testcafe picks it up too, as both chrome-remote-interface and testcafe-hammerhead declare ws: ^7.x), runs hang
intermittently: the browser shows a blank page between tests and the run sits there until the pipeline timeout. It is usually the same payload-heavy test that trips it, and the same test passes in isolation.
The console shows:

Unhandled promise rejection:
Error: WebSocket connection closed
at .../chrome-remote-interface/lib/chrome.js:94:35
at Chrome._handleConnectionClose (.../chrome-remote-interface/lib/chrome.js:256:13)
...
at WebSocket.emitClose (.../ws/lib/websocket.js:252:10)

Root cause (analyzed):

ws 7.5.11 backported two DoS-hardening receiver limits that are enabled by default: maxBufferedChunks and maxFragments. 7.5.12 lowered the defaults to 262,144 chunks / 16,384 fragments and started counting
empty fragments (ws releases). When a message exceeds a limit, the receiver errors with WS_ERR_TOO_MANY_BUFFERED_PARTS (close code 1008) and the connection dies.

CDP legitimately sends very large, heavily fragmented messages (snapshots, response bodies). Neither consumer configures the new options:

  • chrome-remote-interface/lib/chrome.js creates the CDP socket with only maxPayload, perMessageDeflate, followRedirects;
  • testcafe-hammerhead/lib/proxy/index.js creates its two ws.Servers with no options at all.

So a large CDP payload kills the DevTools connection mid-run, native automation loses the browser, and the run hangs. This is likely also behind some earlier "WebSocket connection closed" reports, e.g. #8286, #8300.

What is the Expected behavior?

TestCafe should keep control of the browser: either pass maxFragments: 0, maxBufferedChunks: 0 (or suitably high values) on its ws sockets/servers, or pin a known-good ws. The CDP and hammerhead sockets only talk to a localhost browser, so the DoS hardening these defaults provide does not apply there.

What is the public URL of the test page? (attach your complete example)

This concerns an internal app

What is your TestCafe test code?

This concerns an internal app

Your complete configuration file

No response

Your complete test report

No response

Screenshots

No response

Steps to Reproduce

  1. Install testcafe so that ws resolves to 7.5.12 (any fresh install; 7.5.11 has the same mechanism with 8x higher limits).
  2. Run a long suite against a page where CDP transfers large payloads.
  3. Intermittently: blank page between tests, hang until timeout, Error: WebSocket connection closed unhandled rejection.

Workaround: pin ws to 7.5.10 via npm overrides — confirmed to resolve the hang for us.

TestCafe version

3.7.6

Node.js version

26.4.0

Command-line arguments

testcafe chrome suites/*.test.ts

Browser name(s) and version(s)

Chrome 150 (native automation)

Platform(s) and version(s)

macOS and Linux CI agents

Other

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    STATE: Need responseAn issue that requires a response or attention from the team.TYPE: bugThe described behavior is considered as wrong (bug).

    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