Reducing the Failure to Raw CDP Pipe Transport

Summary

  • A Node.js harness reproduced the native Edge crash without Playwright, Puppeteer, Selenium, or third-party packages.
  • Edge, profile state, input files, CDP commands, and shutdown procedure were held constant while the transport changed.
  • Raw CDP over pipe crashed on the second or third browser process after profile reuse.
  • Raw CDP over port completed 8 / 8 runs, with matching file sizes and SHA-256 hashes.

Why remove Playwright

The earlier tests had excluded the original profile, headless mode, and download.save_as() as required causes. Playwright’s launch behavior and command ordering still remained in the system.

Reproducing the same native termination without Playwright would establish that the Python application and Playwright’s higher-level Download API were not necessary conditions.

The reduced harness uses only:

  • Node.js standard modules;
  • Microsoft Edge;
  • a dedicated test profile;
  • a local HTTP server;
  • raw CDP JSON messages.

Dependency-free harness

The reproduction performs the following steps:

  1. Starts an HTTP server on localhost.
  2. Generates a deterministic 5 MiB file and an HTML page containing five download links.
  3. Creates a new Edge profile in a test-only user-data directory.
  4. Opens the page and configures download behavior through CDP.
  5. Activates each link and waits for the file.
  6. Validates file size and SHA-256.
  7. Closes Edge with Browser.close.
  8. Starts the next Edge process with the same profile.

The test does not depend on an external website, a personal Edge profile, extensions, or authentication state.

Transport comparison

CDP commands can reach Edge through two transport paths:

Transport Launch option Connection
Pipe --remote-debugging-pipe Dedicated parent-child process pipes
Port --remote-debugging-port Local HTTP and WebSocket endpoint

Both paths carry CDP messages. This makes the transport a useful independent variable when the remaining conditions are fixed.

Pipe result

The pipe test used the following form:

node repro.mjs --transport pipe --iterations 5 --download-behavior allow

The first Edge process and its downloads completed. Edge then terminated during the second process, or during the third process in some attempts.

run=1 transport=pipe result=ok
run=2 transport=pipe result=failed
exit_code=3221225477 (0xC0000005)

Some failed runs left a fully written 5 MiB .crdownload file that had not been renamed to the final filename. This is consistent with a failure near download completion, but it does not identify the exact internal operation.

Port result

Only the transport argument changed:

node repro.mjs --transport port --iterations 8 --download-behavior allow

All eight processes completed successfully.

run=1 transport=port result=ok
run=2 transport=port result=ok
run=3 transport=port result=ok
run=4 transport=port result=ok
run=5 transport=port result=ok
run=6 transport=port result=ok
run=7 transport=port result=ok
run=8 transport=port result=ok

Every downloaded file had the expected 5 MiB size and SHA-256 hash.

Controlled variables

The comparison held these inputs constant:

  • Edge 152.0.4191.53 executable;
  • user-data directory;
  • generated 5 MiB HTTP response;
  • HTML and link activation;
  • Browser.setDownloadBehavior command;
  • target creation and attachment sequence;
  • Browser.close shutdown procedure.

The independent variable was:

A: --remote-debugging-pipe
B: --remote-debugging-port=<temporary local port>

Cross-checks

Configuration Observed result
Edge 152 + raw CDP pipe Native crash on the second or third process
Edge 152 + raw CDP port 8 / 8 successful
Edge 152 launched over port, Playwright attached 2 / 2 successful
Playwright-bundled Chromium 151 + persistent pipe 25 / 25 successful
New Edge profile, first browser process only 5 / 5 successful

Chromium 151 and Edge 152 are not identical versions, so this comparison alone cannot establish an Edge 152 regression. It does show that the failure was not universal across the tested Chromium-based browser paths.

Narrowed failure boundary

The reproduction was narrowed to the following observed combination:

Microsoft Edge 152
same profile reused by another Edge process
download performed under CDP control
remote-debugging-pipe transport
native process crash

Changing to a port transport, changing to the bundled Chromium build, or limiting the test to the first Edge process did not reproduce the crash in the recorded runs.

Eight successful port runs are a useful control, not proof that the port path is safe across every environment. The precise claim is that the crash did not reproduce over port in the tested environment and run count while other relevant conditions were held fixed.

Next test

The final step compares Crashpad dumps from headed, headless, and raw CDP runs to determine whether those paths converge on the same native failure signature.