From 9c53176f934a7bf8318b137fd78090d0010ec29d Mon Sep 17 00:00:00 2001 From: mjoffre Date: Thu, 21 May 2026 01:36:07 +0000 Subject: [PATCH] fix: check HTTP status before parsing JSON in multipart upload - Reorder handle_response_error() before json.loads() in _upload_part, _initiate_multipart_upload, and _complete_multipart_upload so that server errors (empty body, 502, etc.) raise a clear ResponseError instead of a cryptic JSONDecodeError. - Reduce MAX_PARALLEL_UPLOADS from 20 to 3 (matching the TypeScript SDK) to avoid overwhelming the sandbox API. - Replace print() with logger.warning() in _abort_multipart_upload. Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- src/blaxel/core/sandbox/default/filesystem.py | 12 ++++++------ src/blaxel/core/sandbox/sync/filesystem.py | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/blaxel/core/sandbox/default/filesystem.py b/src/blaxel/core/sandbox/default/filesystem.py index 49ecc044..c5e8a1d5 100644 --- a/src/blaxel/core/sandbox/default/filesystem.py +++ b/src/blaxel/core/sandbox/default/filesystem.py @@ -21,7 +21,7 @@ # Multipart upload constants MULTIPART_THRESHOLD = 5 * 1024 * 1024 # 5MB CHUNK_SIZE = 5 * 1024 * 1024 # 5MB per part -MAX_PARALLEL_UPLOADS = 20 # Number of parallel part uploads +MAX_PARALLEL_UPLOADS = 3 # Number of parallel part uploads logger = logging.getLogger(__name__) @@ -480,8 +480,8 @@ async def _initiate_multipart_upload( client = self.get_client() response = await client.post(url, json=body, headers=headers) try: - data = json.loads(await response.aread()) self.handle_response_error(response) + data = json.loads(await response.aread()) return data finally: await response.aclose() @@ -498,9 +498,9 @@ async def _upload_part(self, upload_id: str, part_number: int, data: bytes) -> D client = self.get_client() response = await client.put(url, files=files, params=params, headers=headers) try: - data = json.loads(await response.aread()) self.handle_response_error(response) - return data + result = json.loads(await response.aread()) + return result finally: await response.aclose() @@ -515,8 +515,8 @@ async def _complete_multipart_upload( client = self.get_client() response = await client.post(url, json=body, headers=headers) try: - data = json.loads(await response.aread()) self.handle_response_error(response) + data = json.loads(await response.aread()) return SuccessResponse.from_dict(data) finally: await response.aclose() @@ -531,7 +531,7 @@ async def _abort_multipart_upload(self, upload_id: str) -> None: try: # Don't raise error if abort fails - we want to throw the original error if not response.is_success: - print(f"Warning: Failed to abort multipart upload: {response.status_code}") + logger.warning(f"Failed to abort multipart upload: {response.status_code}") finally: await response.aclose() diff --git a/src/blaxel/core/sandbox/sync/filesystem.py b/src/blaxel/core/sandbox/sync/filesystem.py index 1b8037d1..b263057d 100644 --- a/src/blaxel/core/sandbox/sync/filesystem.py +++ b/src/blaxel/core/sandbox/sync/filesystem.py @@ -23,7 +23,7 @@ # Multipart upload constants MULTIPART_THRESHOLD = 5 * 1024 * 1024 # 5MB CHUNK_SIZE = 5 * 1024 * 1024 # 5MB per part -MAX_PARALLEL_UPLOADS = 20 # Number of parallel part uploads +MAX_PARALLEL_UPLOADS = 3 # Number of parallel part uploads class SyncSandboxFileSystem(SyncSandboxAction):