From 662701334108c9f6c7645b773a05745056e16441 Mon Sep 17 00:00:00 2001 From: Maxwell Calkin Date: Sun, 8 Mar 2026 23:15:06 -0400 Subject: [PATCH] fix: use RateLimitException/RateLimitError consistently for 429 responses MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both Python and JS SDKs had inconsistent error handling for rate limit (429) responses in the envd API layer — returning generic SandboxException/SandboxError instead of RateLimitException/RateLimitError. This made it impossible for users to programmatically catch and handle rate limiting separately from other errors. Changes: - Python SDK envd/api.py: return RateLimitException instead of SandboxException for 429 status codes - Python SDK __init__.py: export RateLimitException so users can import it via `from e2b import RateLimitException` (parity with JS SDK which already exports RateLimitError) - JS SDK envd/api.ts: return RateLimitError instead of SandboxError for 429 status codes - JS SDK envd/rpc.ts: add ResourceExhausted gRPC code handler returning RateLimitError (parity with Python SDK rpc.py which already handles it) AI Disclosure: This PR was authored by Claude, an AI assistant by Anthropic (claude.ai/claude-code), operating transparently and not impersonating a human. Co-Authored-By: Claude Opus 4.6 --- packages/js-sdk/src/envd/api.ts | 3 ++- packages/js-sdk/src/envd/rpc.ts | 5 +++++ packages/python-sdk/e2b/__init__.py | 2 ++ packages/python-sdk/e2b/envd/api.py | 3 ++- 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/packages/js-sdk/src/envd/api.ts b/packages/js-sdk/src/envd/api.ts index 960a03ded6..201f5beed8 100644 --- a/packages/js-sdk/src/envd/api.ts +++ b/packages/js-sdk/src/envd/api.ts @@ -8,6 +8,7 @@ import { InvalidArgumentError, NotFoundError, NotEnoughSpaceError, + RateLimitError, formatSandboxTimeoutError, AuthenticationError, } from '../errors' @@ -38,7 +39,7 @@ export async function handleEnvdApiError(res: { case 404: return new NotFoundError(message) case 429: - return new SandboxError( + return new RateLimitError( `${res.response.status}: ${message}: The requests are being rate limited.` ) case 502: diff --git a/packages/js-sdk/src/envd/rpc.ts b/packages/js-sdk/src/envd/rpc.ts index 9ad34ec6e8..80670de04a 100644 --- a/packages/js-sdk/src/envd/rpc.ts +++ b/packages/js-sdk/src/envd/rpc.ts @@ -8,6 +8,7 @@ import { formatSandboxTimeoutError, InvalidArgumentError, NotFoundError, + RateLimitError, SandboxError, TimeoutError, } from '../errors' @@ -24,6 +25,10 @@ export function handleRpcError(err: unknown): Error { return new NotFoundError(err.message) case Code.Unavailable: return formatSandboxTimeoutError(err.message) + case Code.ResourceExhausted: + return new RateLimitError( + `${err.message}: Rate limit exceeded, please try again later.` + ) case Code.Canceled: return new TimeoutError( `${err.message}: This error is likely due to exceeding 'requestTimeoutMs'. You can pass the request timeout value as an option when making the request.` diff --git a/packages/python-sdk/e2b/__init__.py b/packages/python-sdk/e2b/__init__.py index 264fd5deee..f62b986e93 100644 --- a/packages/python-sdk/e2b/__init__.py +++ b/packages/python-sdk/e2b/__init__.py @@ -42,6 +42,7 @@ InvalidArgumentException, NotEnoughSpaceException, NotFoundException, + RateLimitException, SandboxException, TemplateException, TimeoutException, @@ -127,6 +128,7 @@ "GitUpstreamException", "InvalidArgumentException", "NotEnoughSpaceException", + "RateLimitException", "TemplateException", "BuildException", "FileUploadException", diff --git a/packages/python-sdk/e2b/envd/api.py b/packages/python-sdk/e2b/envd/api.py index 2c5670d5d0..7c400c0e82 100644 --- a/packages/python-sdk/e2b/envd/api.py +++ b/packages/python-sdk/e2b/envd/api.py @@ -7,6 +7,7 @@ AuthenticationException, InvalidArgumentException, NotEnoughSpaceException, + RateLimitException, format_sandbox_timeout_exception, ) @@ -50,7 +51,7 @@ def format_envd_api_exception(status_code: int, message: str): elif status_code == 404: return NotFoundException(message) elif status_code == 429: - return SandboxException(f"{message}: The requests are being rate limited.") + return RateLimitException(f"{message}: The requests are being rate limited.") elif status_code == 502: return format_sandbox_timeout_exception(message) elif status_code == 507: