Skip to content

fix(python-sdk): raise SandboxException instead of bare Exception when command stream ends without exit event - #1727

Open
AdaAibaby wants to merge 2 commits into
e2b-dev:mainfrom
AdaAibaby:fix/command-handle-sandbox-exception
Open

fix(python-sdk): raise SandboxException instead of bare Exception when command stream ends without exit event#1727
AdaAibaby wants to merge 2 commits into
e2b-dev:mainfrom
AdaAibaby:fix/command-handle-sandbox-exception

Conversation

@AdaAibaby

Copy link
Copy Markdown

Summary

  • CommandHandle.wait() (sync) and AsyncCommandHandle.wait() (async) raised a bare Exception("Command ended without an end event") when the command stream closed without a ConnectRPC end event.
  • This surfaces as an opaque Exception instead of a SandboxException, breaking except SandboxException handlers and giving no indication that the sandbox lifecycle is the cause.

Change

Replace the bare Exception with SandboxException in both sandbox_sync and sandbox_async:

# before
raise Exception("Command ended without an end event")

# after
raise SandboxException(
    "Command stream ended without an exit event. "
    "The sandbox may have been killed, paused, or timed out."
)

Context

This path is reached when the transport closes the stream before a ConnectRPC end envelope arrives — e.g. when a sandbox is killed or times out mid-command and the connection is dropped at the TCP level. The transport failure itself is already caught and mapped by handle_rpc_exception_with_health (which raises TimeoutException when the sandbox health probe confirms it is gone). This result is None branch is the fallback for cases where the stream closed cleanly but no end event was received.

Closes #1726 (Problem 3).

@AdaAibaby
AdaAibaby requested a review from mishushakov as a code owner August 20, 2026 09:31
@cla-bot cla-bot Bot added the cla-signed label Aug 20, 2026
@changeset-bot

changeset-bot Bot commented Aug 20, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 97b646b

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

This PR includes changesets to release 1 package
Name Type
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

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

Copy link
Copy Markdown

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: c6aed678f7

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread packages/python-sdk/e2b/sandbox_async/commands/command_handle.py

@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 of the error-class change (checked T-1/T-1c parity, T-57/T-58 error hierarchy, T-62 actionable messages, T-69/T-71 docstrings).

The core of the change is right: a bare Exception here violated T-57 (sandbox failures extend SandboxException) and the fix matches the JS surface, which already throws SandboxError at the same spot. Keeping the base SandboxException rather than a specific subclass is also correct under T-58 here, since the cause is genuinely unknown at that point (transport failures are already mapped to TimeoutException upstream).

2 violations, both inline.

Not tied to a changed line: T-69/T-71wait()'s docstring in both files still documents only CommandExitException ("If the command exits with a non-zero exit code, it throws a CommandExitException"). T-62 requires documenting when an error is thrown, so the new SandboxException path belongs in the docstring, in reST field style (e.g. :raises SandboxException: the command stream ended before an exit event, e.g. the sandbox was killed or timed out). Same for the async variant.

Comment thread packages/python-sdk/e2b/sandbox_sync/commands/command_handle.py
Comment thread packages/python-sdk/e2b/sandbox_async/commands/command_handle.py
@mishushakov

Copy link
Copy Markdown
Member

/changeset

@devin-ai-integration

Copy link
Copy Markdown
Contributor

This PR already has .changeset/fix-command-handle-sandbox-exception.md, but it only bumps e2b — the Python SDK is changed too and needs a @e2b/python-sdk patch. I can't push to the fork branch (AdaAibaby:fix/command-handle-sandbox-exception, 403), so here is the one-line edit:

 ---
 "e2b": patch
+"@e2b/python-sdk": 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.
+Raise `SandboxException`/`SandboxError` instead of a bare `Exception` from `CommandHandle.wait()` when the command stream ends without an exit event, with a clearer message when the sandbox was killed, paused, or timed out mid-stream.

Written by Devin

@devin-ai-integration

Copy link
Copy Markdown
Contributor

PR #1727 already had a changeset, but it only bumped e2b while the PR also changes the Python SDK — needs "@e2b/python-sdk": patch. I can't push to the fork branch (403 on AdaAibaby/E2B), so I left the exact diff as a PR comment for the author/maintainer to apply.

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.

Python SDK: unhandled RemoteProtocolError (TLS close_notify) during command streaming when sandbox ends

3 participants