Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions packages/js-sdk/src/envd/rpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
NotFoundError,
SandboxError,
TimeoutError,
TimeoutType,
} from '../errors'
import { ENVD_DEFAULT_USER } from './versions'

Expand All @@ -26,11 +27,15 @@ export function handleRpcError(err: unknown): Error {
return formatSandboxTimeoutError(err.message)
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.`
`${err.message}: This error is likely due to exceeding 'requestTimeoutMs'. You can pass the request timeout value as an option when making the request.`,
undefined,
TimeoutType.REQUEST
)
case Code.DeadlineExceeded:
return new TimeoutError(
`${err.message}: This error is likely due to exceeding 'timeoutMs' — the total time a long running request (like command execution or directory watch) can be active. It can be modified by passing 'timeoutMs' when making the request. Use '0' to disable the timeout.`
`${err.message}: This error is likely due to exceeding 'timeoutMs' — the total time a long running request (like command execution or directory watch) can be active. It can be modified by passing 'timeoutMs' when making the request. Use '0' to disable the timeout.`,
undefined,
TimeoutType.EXECUTION
)
default:
return new SandboxError(`${err.code}: ${err.message}`)
Expand Down
48 changes: 40 additions & 8 deletions packages/js-sdk/src/errors.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,31 @@
/**
* The type of timeout that occurred.
*
* - `sandbox` — the sandbox itself timed out (e.g., idle timeout expired).
* - `request` — the HTTP request timed out (exceeded `requestTimeoutMs`).
* - `execution` — a long-running operation timed out (exceeded `timeoutMs` for command execution, watch, etc.).
*/
export enum TimeoutType {
/**
* The sandbox itself timed out (e.g., idle timeout expired).
*/
SANDBOX = 'sandbox',
/**
* The HTTP request timed out (exceeded `requestTimeoutMs`).
*/
REQUEST = 'request',
/**
* A long-running operation timed out (exceeded `timeoutMs` for command execution, watch, etc.).
*/
EXECUTION = 'execution',
}

// This is the message for the sandbox timeout error when the response code is 502/Unavailable
export function formatSandboxTimeoutError(message: string) {
return new TimeoutError(
`${message}: This error is likely due to sandbox timeout. You can modify the sandbox timeout by passing 'timeoutMs' when starting the sandbox or calling '.setTimeout' on the sandbox with the desired timeout.`
`${message}: This error is likely due to sandbox timeout. You can modify the sandbox timeout by passing 'timeoutMs' when starting the sandbox or calling '.setTimeout' on the sandbox with the desired timeout.`,
undefined,
TimeoutType.SANDBOX
)
}

Expand All @@ -23,18 +47,26 @@ export class SandboxError extends Error {
/**
* Thrown when a timeout error occurs.
*
* The [unavailable] error type is caused by sandbox timeout.
* The {@link type} property indicates the kind of timeout:
*
* The [canceled] error type is caused by exceeding request timeout.
*
* The [deadline_exceeded] error type is caused by exceeding the timeout for command execution, watch, etc.
*
* The [unknown] error type is sometimes caused by the sandbox timeout when the request is not processed correctly.
* - {@link TimeoutType.SANDBOX} — the sandbox itself timed out (idle timeout, etc.).
* - {@link TimeoutType.REQUEST} — the HTTP request exceeded `requestTimeoutMs`.
* - {@link TimeoutType.EXECUTION} — a long-running operation exceeded its `timeoutMs`.
*/
export class TimeoutError extends SandboxError {
constructor(message: string, stackTrace?: string) {
/**
* The type of timeout that occurred.
*/
readonly type: TimeoutType

constructor(
message: string,
stackTrace?: string,
type: TimeoutType = TimeoutType.SANDBOX
) {
super(message, stackTrace)
this.name = 'TimeoutError'
this.type = type
}
}

Expand Down
1 change: 1 addition & 0 deletions packages/js-sdk/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export {
SandboxError,
TemplateError,
TimeoutError,
TimeoutType,
RateLimitError,
BuildError,
FileUploadError,
Expand Down
2 changes: 2 additions & 0 deletions packages/python-sdk/e2b/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
SandboxException,
TemplateException,
TimeoutException,
TimeoutType,
)
from .sandbox.commands.command_handle import (
CommandExitException,
Expand Down Expand Up @@ -121,6 +122,7 @@
# Exceptions
"SandboxException",
"TimeoutException",
"TimeoutType",
"NotFoundException",
"AuthenticationException",
"GitAuthException",
Expand Down
7 changes: 5 additions & 2 deletions packages/python-sdk/e2b/envd/rpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
InvalidArgumentException,
NotFoundException,
TimeoutException,
TimeoutType,
format_sandbox_timeout_exception,
AuthenticationException,
RateLimitException,
Expand All @@ -33,11 +34,13 @@ def handle_rpc_exception(e: Exception):
)
elif e.status == Code.canceled:
return TimeoutException(
f"{e.message}: This error is likely due to exceeding 'request_timeout'. You can pass the request timeout value as an option when making the request."
f"{e.message}: This error is likely due to exceeding 'request_timeout'. You can pass the request timeout value as an option when making the request.",
type=TimeoutType.REQUEST,
)
elif e.status == Code.deadline_exceeded:
return TimeoutException(
f"{e.message}: This error is likely due to exceeding 'timeout' — the total time a long running request (like process or directory watch) can be active. It can be modified by passing 'timeout' when making the request. Use '0' to disable the timeout."
f"{e.message}: This error is likely due to exceeding 'timeout' — the total time a long running request (like process or directory watch) can be active. It can be modified by passing 'timeout' when making the request. Use '0' to disable the timeout.",
type=TimeoutType.EXECUTION,
)
else:
return SandboxException(f"{e.status}: {e.message}")
Expand Down
35 changes: 29 additions & 6 deletions packages/python-sdk/e2b/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,38 @@
from enum import Enum


class TimeoutType(str, Enum):
"""
The type of timeout that occurred.

- ``SANDBOX``: The sandbox itself timed out (e.g., idle timeout expired).
- ``REQUEST``: The HTTP request timed out (exceeded ``request_timeout``).
- ``EXECUTION``: A long-running operation timed out (exceeded ``timeout`` for command execution, watch, etc.).
"""

SANDBOX = "sandbox"
REQUEST = "request"
EXECUTION = "execution"


def format_sandbox_timeout_exception(message: str):
return TimeoutException(
f"{message}: This error is likely due to sandbox timeout. You can modify the sandbox timeout by passing 'timeout' when starting the sandbox or calling '.set_timeout' on the sandbox with the desired timeout."
f"{message}: This error is likely due to sandbox timeout. You can modify the sandbox timeout by passing 'timeout' when starting the sandbox or calling '.set_timeout' on the sandbox with the desired timeout.",
type=TimeoutType.SANDBOX,
)


def format_request_timeout_error() -> Exception:
return TimeoutException(
"Request timed out — the 'request_timeout' option can be used to increase this timeout",
type=TimeoutType.REQUEST,
)


def format_execution_timeout_error() -> Exception:
return TimeoutException(
"Execution timed out — the 'timeout' option can be used to increase this timeout",
type=TimeoutType.EXECUTION,
)


Expand All @@ -30,13 +50,16 @@ class TimeoutException(SandboxException):
"""
Raised when a timeout occurs.

The `unavailable` exception type is caused by sandbox timeout.\n
The `canceled` exception type is caused by exceeding request timeout.\n
The `deadline_exceeded` exception type is caused by exceeding the timeout for process, watch, etc.\n
The `unknown` exception type is sometimes caused by the sandbox timeout when the request is not processed correctly.\n
The ``type`` attribute indicates the kind of timeout:

- :attr:`TimeoutType.SANDBOX` — the sandbox itself timed out (idle timeout, etc.).
- :attr:`TimeoutType.REQUEST` — the HTTP request exceeded ``request_timeout``.
- :attr:`TimeoutType.EXECUTION` — a long-running operation exceeded its ``timeout``.
"""

pass
def __init__(self, message: str, type: TimeoutType = TimeoutType.SANDBOX):
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve no-arg construction for TimeoutException

This new __init__ requires a message, which is a behavioral break from the previous Exception-inherited constructor that allowed TimeoutException() / raise TimeoutException with no arguments. Downstream code that synthesizes this exception in tests, mocks, or wrappers will now raise TypeError before it can be handled, so the change is not fully backward compatible as described.

Useful? React with 👍 / 👎.

super().__init__(message)
self.type = type


class InvalidArgumentException(SandboxException):
Expand Down