Version
1.61.0 (latest release)
Steps to reproduce
Minimal reproduction: https://github.com/karmas056/playwright-init-task-repro
-
Clone the repository:
git clone https://github.com/karmas056/playwright-init-task-repro.git
cd playwright-init-task-repro
-
Build and run it:
docker build -t playwright-init-task-repro .
docker run --rm playwright-init-task-repro
The reproduction injects a minimal Transport that deterministically closes
while Connection.init is pending. It does not launch a browser or a real
Playwright Node driver, so it isolates the Python startup cleanup path from
browser and operating-system behavior.
The script exits successfully only after the event loop observes an unconsumed
Connection.run.<locals>.init task.
Expected behavior
The transport/startup exception should be raised to the caller, and every
internal task created by the failed startup attempt should be awaited,
cancelled, or have its exception consumed.
Garbage collection should not produce a secondary
Task exception was never retrieved warning.
Actual behavior
The original startup exception is raised to the caller, but after gc.collect()
the event loop reports an unconsumed internal init task:
startup_error=Exception: Connection closed while reading from the driver (forced repro)
result=REPRODUCED
task=Connection.run.<locals>.init
unretrieved_exception=Exception: Connection.init: Connection closed while reading from the driver (forced repro)
Task exception was never retrieved
future: <Task finished name='Task-3' coro=<Connection.run.<locals>.init() ...>
The relevant traceback ends with:
File "playwright/_impl/_connection.py", line 310, in init
self.playwright_future.set_result(await self._root_object.initialize())
...
Exception: Connection.init: Connection closed while reading from the driver (forced repro)
Additional context
This was initially observed after a real, intermittent driver disconnect in a
long-running asyncio scheduler. A startup attempt logged
Connection closed while reading from the driver, retried successfully, and a
later garbage-collection cycle reported the abandoned init-task exception.
The deterministic reproduction points to the following startup path:
I searched the existing issues. #2091 has a related unhandled
Connection.run() startup task, and #650 covers transport errors during
context-manager initialization, but I did not find an issue covering this
completed _init_task cleanup path.
Environment
- Operating System: Debian GNU/Linux 13 (trixie), Docker
- CPU: x86_64
- Browser: N/A (the failure and reproduction occur before browser launch)
- Python Version: 3.12.13
- Playwright Version: 1.61.0
Version
1.61.0 (latest release)
Steps to reproduce
Minimal reproduction: https://github.com/karmas056/playwright-init-task-repro
Clone the repository:
git clone https://github.com/karmas056/playwright-init-task-repro.git cd playwright-init-task-reproBuild and run it:
docker build -t playwright-init-task-repro . docker run --rm playwright-init-task-reproThe reproduction injects a minimal
Transportthat deterministically closeswhile
Connection.initis pending. It does not launch a browser or a realPlaywright Node driver, so it isolates the Python startup cleanup path from
browser and operating-system behavior.
The script exits successfully only after the event loop observes an unconsumed
Connection.run.<locals>.inittask.Expected behavior
The transport/startup exception should be raised to the caller, and every
internal task created by the failed startup attempt should be awaited,
cancelled, or have its exception consumed.
Garbage collection should not produce a secondary
Task exception was never retrievedwarning.Actual behavior
The original startup exception is raised to the caller, but after
gc.collect()the event loop reports an unconsumed internal init task:
The relevant traceback ends with:
Additional context
This was initially observed after a real, intermittent driver disconnect in a
long-running asyncio scheduler. A startup attempt logged
Connection closed while reading from the driver, retried successfully, and alater garbage-collection cycle reported the abandoned init-task exception.
The deterministic reproduction points to the following startup path:
PlaywrightContextManager.__aenter__createsConnection.run()withloop.create_task(...)and waits for eitheron_error_futureorplaywright_future:https://github.com/microsoft/playwright-python/blob/v1.61.0/playwright/async_api/_context_manager.py#L29-L48
Connection.run()stores a second task in_init_task:https://github.com/microsoft/playwright-python/blob/v1.61.0/playwright/_impl/_connection.py#L305-L314
__aenter__raises, so__aexit__is notentered.
Connection.cleanup()only cancels_init_taskwhile it is still pending;it does not retrieve an exception from an already completed
_init_task:https://github.com/microsoft/playwright-python/blob/v1.61.0/playwright/_impl/_connection.py#L327-L330
I searched the existing issues. #2091 has a related unhandled
Connection.run()startup task, and #650 covers transport errors duringcontext-manager initialization, but I did not find an issue covering this
completed
_init_taskcleanup path.Environment