From 89a181bdc6a811a75ed3be5b06c8205d126d9718 Mon Sep 17 00:00:00 2001 From: Mohammed Alkindi Date: Fri, 18 Sep 2026 09:03:05 -0700 Subject: [PATCH] fix(stream): close the file handle when save_as fails save_as closed the file only after the read loop completed, so an exception from the channel skipped the close. WritableStream.copy handles the upload direction with a context manager already. --- playwright/_impl/_stream.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/playwright/_impl/_stream.py b/playwright/_impl/_stream.py index 04afa48e1..ba0adb762 100644 --- a/playwright/_impl/_stream.py +++ b/playwright/_impl/_stream.py @@ -27,14 +27,16 @@ def __init__( async def save_as(self, path: Union[str, Path]) -> None: file = await self._loop.run_in_executor(None, lambda: open(path, "wb")) - while True: - binary = await self._channel.send("read", None, {"size": 1024 * 1024}) - if not binary: - break - await self._loop.run_in_executor( - None, lambda: file.write(base64.b64decode(binary)) - ) - await self._loop.run_in_executor(None, lambda: file.close()) + try: + while True: + binary = await self._channel.send("read", None, {"size": 1024 * 1024}) + if not binary: + break + await self._loop.run_in_executor( + None, lambda: file.write(base64.b64decode(binary)) + ) + finally: + await self._loop.run_in_executor(None, lambda: file.close()) async def read_all(self) -> bytes: binary = b""