Skip to content

Commit 17cce6a

Browse files
mishushakovclaude
andcommitted
Use TimeoutError for confirmed sandbox-killed errors
Matches the existing 502 mapping in extractError/extract_exception and the base SDK convention: a dead sandbox surfaces as TimeoutError / TimeoutException. When the health probe is inconclusive or the sandbox is still running, the original transport error propagates unchanged. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 4c0e50a commit 17cce6a

6 files changed

Lines changed: 17 additions & 13 deletions

File tree

.changeset/grumpy-sloths-relax.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@
33
'@e2b/code-interpreter-python': patch
44
---
55

6-
Throw a descriptive sandbox error instead of a raw socket error (e.g. `ECONNRESET`) when the sandbox is killed or times out while a request (`runCode`/`run_code`, context management) is in progress
6+
Throw a descriptive `TimeoutError`/`TimeoutException` instead of a raw socket error (e.g. `ECONNRESET`) when the sandbox is killed or times out while a request (`runCode`/`run_code`, context management) is in progress

js/src/sandbox.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Sandbox as BaseSandbox, InvalidArgumentError, SandboxError } from 'e2b'
1+
import { Sandbox as BaseSandbox, InvalidArgumentError, TimeoutError } from 'e2b'
22

33
import {
44
Result,
@@ -435,7 +435,7 @@ export class Sandbox extends BaseSandbox {
435435
}
436436

437437
/**
438-
* Throws a descriptive `SandboxError` if the connection error was caused
438+
* Throws a descriptive `TimeoutError` if the connection error was caused
439439
* by the sandbox being killed mid-request. If the sandbox is still running
440440
* (or its state can't be determined), returns so the caller can re-throw
441441
* the original error.
@@ -448,7 +448,7 @@ export class Sandbox extends BaseSandbox {
448448
// original error instead of wrongly claiming the sandbox is gone.
449449
(await this.isRunning().catch(() => true)) === false
450450
) {
451-
throw new SandboxError(
451+
throw new TimeoutError(
452452
'The sandbox was killed while the request was in progress. This can happen when the sandbox times out or is killed manually. ' +
453453
"You can modify the sandbox timeout by passing 'timeoutMs' when starting the sandbox or calling '.setTimeout' on the sandbox with the desired timeout."
454454
)

js/tests/killedSandbox.test.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { TimeoutError } from 'e2b'
12
import { expect } from 'vitest'
23

34
import { isDebug, sandboxTest, wait } from './setup'
@@ -6,9 +7,12 @@ sandboxTest.skipIf(isDebug)(
67
'runCode throws a descriptive error when the sandbox is killed during execution',
78
async ({ sandbox }) => {
89
const execution = sandbox.runCode('import time; time.sleep(60)')
9-
const assertion = expect(execution).rejects.toThrowError(
10-
/sandbox was killed while the request was in progress/
11-
)
10+
const assertion = Promise.all([
11+
expect(execution).rejects.toThrowError(
12+
/sandbox was killed while the request was in progress/
13+
),
14+
expect(execution).rejects.toBeInstanceOf(TimeoutError),
15+
])
1216

1317
await wait(2_000)
1418
await sandbox.kill()

python/e2b_code_interpreter/exceptions.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from e2b import SandboxException, TimeoutException
1+
from e2b import TimeoutException
22

33

44
def format_request_timeout_error() -> Exception:
@@ -14,7 +14,7 @@ def format_execution_timeout_error() -> Exception:
1414

1515

1616
def format_sandbox_killed_error() -> Exception:
17-
return SandboxException(
17+
return TimeoutException(
1818
"The sandbox was killed while the request was in progress. This can happen when the sandbox times out or is killed manually. "
1919
"You can modify the sandbox timeout by passing 'timeout' when starting the sandbox or calling '.set_timeout' on the sandbox with the desired timeout",
2020
)

python/tests/async/test_async_killed.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import pytest
44

5-
from e2b import SandboxException
5+
from e2b import TimeoutException
66
from e2b_code_interpreter import AsyncSandbox
77

88

@@ -18,6 +18,6 @@ async def test_run_code_raises_when_sandbox_is_killed_during_execution(
1818
await async_sandbox.kill()
1919

2020
with pytest.raises(
21-
SandboxException, match="sandbox was killed while the request was in progress"
21+
TimeoutException, match="sandbox was killed while the request was in progress"
2222
):
2323
await execution

python/tests/sync/test_killed.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import pytest
44

5-
from e2b import SandboxException
5+
from e2b import TimeoutException
66
from e2b_code_interpreter import Sandbox
77

88

@@ -13,7 +13,7 @@ def test_run_code_raises_when_sandbox_is_killed_during_execution(sandbox: Sandbo
1313

1414
try:
1515
with pytest.raises(
16-
SandboxException,
16+
TimeoutException,
1717
match="sandbox was killed while the request was in progress",
1818
):
1919
sandbox.run_code("import time; time.sleep(60)")

0 commit comments

Comments
 (0)