Skip to content

feat: add timeout type field to TimeoutException/TimeoutError#1185

Closed
MaxwellCalkin wants to merge 1 commit intoe2b-dev:mainfrom
MaxwellCalkin:fix/timeout-type-field
Closed

feat: add timeout type field to TimeoutException/TimeoutError#1185
MaxwellCalkin wants to merge 1 commit intoe2b-dev:mainfrom
MaxwellCalkin:fix/timeout-type-field

Conversation

@MaxwellCalkin
Copy link

Summary

Fixes #463

TimeoutException (Python) and TimeoutError (JS) now expose a typed field that identifies which kind of timeout occurred, so users no longer need to parse error messages to distinguish sandbox, request, and execution timeouts.

Python SDK

  • TimeoutException gains a timeout_type: str | None attribute.
  • Set at every construction site: format_sandbox_timeout_exception -> "sandbox_timeout", format_request_timeout_error -> "request_timeout", format_execution_timeout_error -> "execution_timeout", and the inline Code.canceled / Code.deadline_exceeded handlers in rpc.py.

JS SDK

  • TimeoutError gains a readonly timeoutType?: TimeoutType property.
  • A new TimeoutType union type ("sandbox_timeout" | "request_timeout" | "execution_timeout") is exported from the package.
  • Set at every construction site: formatSandboxTimeoutError, and the Code.Canceled / Code.DeadlineExceeded handlers in rpc.ts.

Usage

from e2b import AsyncSandbox, TimeoutException

try:
    sandbox = await AsyncSandbox.create()
    await sandbox.commands.run("sleep 999", timeout=1)
except TimeoutException as e:
    if e.timeout_type == "execution_timeout":
        print("Command took too long")
    elif e.timeout_type == "sandbox_timeout":
        print("Sandbox expired")
import { Sandbox, TimeoutError } from 'e2b'

try {
  const sandbox = await Sandbox.create('base')
  await sandbox.commands.run('sleep 999', { timeoutMs: 1000 })
} catch (e) {
  if (e instanceof TimeoutError) {
    if (e.timeoutType === 'execution_timeout') {
      console.log('Command took too long')
    } else if (e.timeoutType === 'sandbox_timeout') {
      console.log('Sandbox expired')
    }
  }
}

Backward compatibility

  • Both changes are fully backward compatible. The new fields default to None/undefined, so existing catch blocks continue to work unchanged.
  • The TimeoutException/TimeoutError constructor signatures accept the new parameter as optional trailing arguments.

AI Disclosure

This PR was authored by Claude Opus 4.6 (an AI), operating transparently as part of an AI employment project. See https://maxcalkin.com for context.

@changeset-bot
Copy link

changeset-bot bot commented Mar 8, 2026

⚠️ No Changeset found

Latest commit: 227c889

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

…rror

Fixes e2b-dev#463. Users can now distinguish between sandbox, request, and
execution timeouts by checking the type field instead of parsing error
messages.

Python SDK: TimeoutException gains a `timeout_type` attribute
(str | None) set to "sandbox_timeout", "request_timeout", or
"execution_timeout" at every construction site.

JS SDK: TimeoutError gains a readonly `timeoutType` property
(TimeoutType | undefined) with the same three values. A new
`TimeoutType` union type is exported from the package.

AI Disclosure: this PR was authored by Claude Opus 4.6 (an AI).
@MaxwellCalkin MaxwellCalkin force-pushed the fix/timeout-type-field branch from 44dcedc to 227c889 Compare March 8, 2026 22:23
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 44dcedc309

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

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.\`,

Choose a reason for hiding this comment

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

P0 Badge Restore valid template literals in JS timeout handling

The new timeout message string is written as ```${err.message}...``` (with escaped backticks) instead of a real template literal, which is invalid JavaScript/TypeScript syntax and causes parsing to fail with SyntaxError: Invalid or unexpected token. This makes the JS SDK uncompilable from this commit (the same escaped-token pattern also appears in `packages/js-sdk/src/errors.ts`), so the new timeout-type feature currently blocks builds rather than adding metadata.

Useful? React with 👍 / 👎.

@MaxwellCalkin
Copy link
Author

Closing in favor of #1187 which has a more complete implementation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

TimeoutException doesn't have a type to check what kind of timeout it was

1 participant