Summary
- Playwright reported
TargetClosedErrorwhile handling a download. - Microsoft Edge had already terminated before
download.save_as()failed. - A new profile completed five downloads during its first browser process, but the failure appeared after reusing that profile across subsequent Edge processes.
- The initial application exception was therefore treated as a symptom. The investigation moved downward through Playwright, CDP transport, and the Edge process itself.
Initial signal
The investigation started with two log entries:
browser_disconnected reason=unexpected
Download.save_as: Target page, context or browser has been closed
Taken alone, these messages suggest a lifecycle problem in the application: the page may have been closed too early, or save_as() may have been called at the wrong time.
Process-level logging changed that interpretation. Edge exited before Playwright attempted to finish the save operation. The sequence was:
Edge process terminates
CDP connection closes
Browser, Context, and Page become unavailable
download.save_as() reports TargetClosedError
The Playwright exception was accurate, but it did not explain why the browser disappeared.
Components involved
| Component | Role in the test |
|---|---|
| Playwright | Starts and controls the browser in the original reproduction |
| Microsoft Edge | Executes the page and download operations |
| CDP | Carries browser automation commands |
| User-data directory | Persists profile state between Edge processes |
| Pipe or port | Provides the CDP transport path |
| Crashpad | Records process crash information |
Playwright’s launch_persistent_context() starts a browser against a specified user-data directory. This is useful when an automated workflow needs to retain cookies or local storage between runs.
That convenience also joins several layers into one API call: Playwright launches Edge, communicates through CDP, Edge performs the network request, and the operating system writes the downloaded file. A generic error at the API boundary can originate in any of those layers.
First reproduction pattern
The initial results appeared to implicate an existing profile:
| Condition | Observed result |
|---|---|
| Previously used profile | Repeated abnormal termination during the download workflow |
| New profile, five downloads in one Edge process | 5 / 5 successful |
The new profile result did not hold after restarting Edge:
New profile, first Edge process -> five downloads succeed
Same profile, later Edge process -> crash on the second or third launch
Multiple independently created profiles showed the same pattern. The meaningful condition was not simply whether a profile was old or new; it was whether the same profile state was reused by another Edge process.
Working hypotheses
At this stage, the plausible explanations included:
- corruption limited to the original profile;
- behavior specific to headless mode;
- an error caused by
download.save_as(); - Playwright-specific browser arguments or CDP command ordering;
- a native failure within Edge.
The next tests changed one condition at a time. Successes and failures were recorded with the same environment, input file, and shutdown sequence wherever possible.
Test environment
The results in this series were observed on September 3, 2026.
| Item | Version |
|---|---|
| Operating system | Windows 11 Home x64, build 26200 |
| Microsoft Edge Stable | 152.0.4191.53, x64 |
| Playwright for Python | 1.62.0 |
| Playwright-bundled Chromium | 151.0.7922.34 |
| Python / Node.js | 3.12.14 / 24.18.1 |
These observations do not establish that every Edge 152 environment is affected. The responsible source component and the regression range were not identified at this point.
Next test
The next note tests the most visible alternatives: a newly created profile, headed versus headless operation, and download handling with and without save_as().