Skip to content

fix(sdk): keep the 5-minute default timeout on sandbox fork - #1898

Draft
rguliyev wants to merge 1 commit into
mainfrom
cursor/fix-fork-default-timeout-b339
Draft

rguliyev wants to merge 1 commit into
mainfrom
cursor/fix-fork-default-timeout-b339

Conversation

@rguliyev

Copy link
Copy Markdown

Summary

Since 2.51.0, Sandbox.fork() / fork() called without an explicit timeout produces sandboxes that expire about 15 seconds after they start instead of the documented 5 minutes.

#1749 removed the SDK-side 5-minute default so that the API default would apply. That reasoning holds for create and connect, which moved to the v2 routes in the same PR (NewSandboxV2.timeout and ConnectSandboxV2.timeout both declare default: 300, and /v2/sandboxes/{id}/connect documents it in prose). Fork was not moved: POST /sandboxes/{sandboxID}/fork still takes SandboxForkRequest, whose timeout carries the legacy default: 15 inherited from v1 NewSandbox.

    SandboxForkRequest:
      type: object
      properties:
        timeout:
          type: integer
          format: int32
          minimum: 0
          default: 15          # <- not 300

So every fork created without timeoutMs / timeout reaches its timeout almost immediately. Where the sandbox lifecycle is configured with onTimeout: 'pause', that presents as forks pausing seconds after they are created; otherwise they are killed.

This restores the documented 5-minute default on the fork path only — create, connect and pause keep deferring to the API — with a comment tying it to the missing v2 fork route so it can be dropped once the API's fork default matches. An explicit timeout is still sent unchanged.

Usage

// before: fork expired ~15s after creation
// after:  fork lives for 5 minutes, as documented
const [fork] = await Sandbox.fork(sandbox.sandboxId)

// unchanged: an explicit timeout is sent as given
const [shortFork] = await Sandbox.fork(sandbox.sandboxId, { timeoutMs: 60_000 })
# before: fork expired ~15s after creation
# after:  fork lives for 5 minutes, as documented
forks = sandbox.fork()

# unchanged: an explicit timeout is sent as given
forks = sandbox.fork(timeout=60)

Tests

packages/js-sdk/tests/sandbox/apiDefaults.test.ts and packages/python-sdk/tests/shared/sandbox/test_api_defaults.py pinned the regression (asserting timeout was absent from the fork body); they now assert the request carries timeout: 300 when the caller omits one, and still assert the explicit value is passed through. count is still omitted when unset — the fork endpoint's count default is 1, which is correct.

Verified with pnpm run format, pnpm run lint, pnpm run typecheck, the mocked JS suites (apiDefaults, lifecycleRequest, onResumeRequest, client) and pytest tests/shared. The live fork integration suites need a real API and were not run here.

Slack Thread

Open in Web Open in Cursor 

The fork endpoint has no v2 route, so an omitted timeout falls back to its
own 15-second default instead of the 300 seconds create and connect get
from /v2. Send the documented 5 minutes when the caller omits one.

Co-authored-by: Rauf Guliyev <rguliyev@users.noreply.github.com>
@cla-bot cla-bot Bot added the cla-signed label Sep 25, 2026
@changeset-bot

changeset-bot Bot commented Sep 25, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 37eca00

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages
Name Type
@e2b/python-sdk Patch
e2b Patch

Not sure what this means? Click here to learn what changesets are.

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

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

TASTE.md review: no violations found in the changed lines.

Checked: T-1 (JS / sync Python / async Python parity — all three fork paths apply the same default), T-44 (timeoutMs ms vs timeout seconds kept), T-47 (default comes from the named constants DEFAULT_SANDBOX_TIMEOUT_MS / SandboxBase.default_sandbox_timeout, no magic numbers, documented via @default and :param timeout: defaults), T-46 (signal still threaded through config.getSignal), T-36 (default is sent once on creation; no background renewal), T-69/T-70/T-71 (docstrings updated on all six fork overload/variant entries).

Not flagged as it predates this PR: the Python fork(sandbox_id, timeout=None, count=None, ...) signature has timeout/count as defaulted positionals rather than keyword-only (T-3a); per T-3a that is a next-major change, not something to fix here.

@github-actions

Copy link
Copy Markdown
Contributor

Package Artifacts

Built from b95bba3. Download artifacts from this workflow run.

JS SDK (e2b@2.51.1-cursor-fix-fork-default-timeout-b339.0):

npm install ./e2b-2.51.1-cursor-fix-fork-default-timeout-b339.0.tgz

CLI (@e2b/cli@2.20.1-cursor-fix-fork-default-timeout-b339.0):

npm install ./e2b-cli-2.20.1-cursor-fix-fork-default-timeout-b339.0.tgz

Code Interpreter JS SDK (@e2b/code-interpreter@2.8.1-cursor-fix-fork-default-timeout-b339.0):

npm install ./e2b-code-interpreter-2.8.1-cursor-fix-fork-default-timeout-b339.0.tgz

Desktop JS SDK (@e2b/desktop@2.4.1-cursor-fix-fork-default-timeout-b339.0):

npm install ./e2b-desktop-2.4.1-cursor-fix-fork-default-timeout-b339.0.tgz

Python SDK (e2b==2.51.0+cursor.fix.fork.default.timeout.b339):

pip install ./e2b-2.51.0+cursor.fix.fork.default.timeout.b339-py3-none-any.whl

Code Interpreter Python SDK (e2b-code-interpreter==2.10.0+cursor.fix.fork.default.timeout.b339):

pip install ./e2b_code_interpreter-2.10.0+cursor.fix.fork.default.timeout.b339-py3-none-any.whl

Desktop Python SDK (e2b-desktop==2.6.0+cursor.fix.fork.default.timeout.b339):

pip install ./e2b_desktop-2.6.0+cursor.fix.fork.default.timeout.b339-py3-none-any.whl

This branch has not been deployed

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants