From c6aed678f7f3885293fc5d273f22438267da246a Mon Sep 17 00:00:00 2001 From: shaolila Date: Thu, 20 Aug 2026 17:29:12 +0800 Subject: [PATCH 1/2] fix(python-sdk): raise SandboxException instead of bare Exception when command stream ends without exit event --- .changeset/fix-command-handle-sandbox-exception.md | 5 +++++ .../python-sdk/e2b/sandbox_async/commands/command_handle.py | 4 +++- .../python-sdk/e2b/sandbox_sync/commands/command_handle.py | 4 +++- 3 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 .changeset/fix-command-handle-sandbox-exception.md diff --git a/.changeset/fix-command-handle-sandbox-exception.md b/.changeset/fix-command-handle-sandbox-exception.md new file mode 100644 index 0000000000..3034e916d0 --- /dev/null +++ b/.changeset/fix-command-handle-sandbox-exception.md @@ -0,0 +1,5 @@ +--- +"e2b": patch +--- + +Raise `SandboxException` instead of bare `Exception` in `CommandHandle.wait()` when the command stream ends without an exit event, giving a clearer error message when the sandbox was killed, paused, or timed out mid-stream. diff --git a/packages/python-sdk/e2b/sandbox_async/commands/command_handle.py b/packages/python-sdk/e2b/sandbox_async/commands/command_handle.py index 4168cfe63d..f3f2dce67c 100644 --- a/packages/python-sdk/e2b/sandbox_async/commands/command_handle.py +++ b/packages/python-sdk/e2b/sandbox_async/commands/command_handle.py @@ -250,7 +250,9 @@ async def wait(self) -> CommandResult: raise self._iteration_exception if self._result is None: - raise Exception("Command ended without an end event") + raise SandboxException( + "Command stream ended without an exit event. The sandbox may have been killed, paused, or timed out." + ) if self._result.exit_code != 0: raise CommandExitException( diff --git a/packages/python-sdk/e2b/sandbox_sync/commands/command_handle.py b/packages/python-sdk/e2b/sandbox_sync/commands/command_handle.py index ea2b3fdad7..b9a2b26018 100644 --- a/packages/python-sdk/e2b/sandbox_sync/commands/command_handle.py +++ b/packages/python-sdk/e2b/sandbox_sync/commands/command_handle.py @@ -193,7 +193,9 @@ def wait( raise self._iteration_exception if self._result is None: - raise Exception("Command ended without an end event") + raise SandboxException( + "Command stream ended without an exit event. The sandbox may have been killed, paused, or timed out." + ) if self._result.exit_code != 0: raise CommandExitException( From 97b646bcec9a5e1758453e1ad0e1d8762a01123f Mon Sep 17 00:00:00 2001 From: shaolila Date: Thu, 20 Aug 2026 18:28:23 +0800 Subject: [PATCH 2/2] fix(python-sdk, js-sdk): update wait() docstrings and sync JS error message --- packages/js-sdk/src/sandbox/commands/commandHandle.ts | 4 +++- .../python-sdk/e2b/sandbox_async/commands/command_handle.py | 2 ++ .../python-sdk/e2b/sandbox_sync/commands/command_handle.py | 2 ++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/js-sdk/src/sandbox/commands/commandHandle.ts b/packages/js-sdk/src/sandbox/commands/commandHandle.ts index 759d17fe51..78e1f0560b 100644 --- a/packages/js-sdk/src/sandbox/commands/commandHandle.ts +++ b/packages/js-sdk/src/sandbox/commands/commandHandle.ts @@ -162,6 +162,8 @@ export class CommandHandle * If the command exits with a non-zero exit code, it throws a `CommandExitError`. * * @returns `CommandResult` result of command execution. + * @throws {CommandExitError} the command exited with a non-zero exit code + * @throws {SandboxError} the command stream ended before an exit event was received, e.g. the sandbox was killed or timed out */ async wait() { await this._wait @@ -171,7 +173,7 @@ export class CommandHandle } if (!this.result) { - throw new SandboxError('Process exited without a result') + throw new SandboxError('Command stream ended without an exit event. The sandbox is no longer running — it may have been killed, paused, or timed out.') } if (this.result.exitCode !== 0) { diff --git a/packages/python-sdk/e2b/sandbox_async/commands/command_handle.py b/packages/python-sdk/e2b/sandbox_async/commands/command_handle.py index f3f2dce67c..9cb5937d6b 100644 --- a/packages/python-sdk/e2b/sandbox_async/commands/command_handle.py +++ b/packages/python-sdk/e2b/sandbox_async/commands/command_handle.py @@ -244,6 +244,8 @@ async def wait(self) -> CommandResult: If the command exits with a non-zero exit code, it throws a `CommandExitException`. :return: `CommandResult` result of command execution + :raises CommandExitException: the command exited with a non-zero exit code + :raises SandboxException: the command stream ended before an exit event was received, e.g. the sandbox was killed or timed out """ await self._wait if self._iteration_exception: diff --git a/packages/python-sdk/e2b/sandbox_sync/commands/command_handle.py b/packages/python-sdk/e2b/sandbox_sync/commands/command_handle.py index b9a2b26018..ef134db43e 100644 --- a/packages/python-sdk/e2b/sandbox_sync/commands/command_handle.py +++ b/packages/python-sdk/e2b/sandbox_sync/commands/command_handle.py @@ -172,6 +172,8 @@ def wait( :param on_stderr: Callback for stderr output :return: `CommandResult` result of command execution + :raises CommandExitException: the command exited with a non-zero exit code + :raises SandboxException: the command stream ended before an exit event was received, e.g. the sandbox was killed or timed out """ try: for stdout, stderr, pty in self: