Skip to content

[Bug]: commands.run hangs indefinitely when sandbox becomes unreachable — request_timeout does not set read timeout on streaming calls #1128

@simsinght

Description

@simsinght

Sandbox ID or Build ID

No response

Environment

e2b==2.8.1
python-sdk

Timestamp of the issue

2026-02-11 15:00 PST

Frequency

One-time occurrence

Expected behavior

if sandbox is unreachable, commands.run should error out

Actual behavior

if sandbox is unreachable, commands.run hangs forever

Issue reproduction

  1. Create a sandbox and run some commands successfully
  2. Wait for the sandbox to become unreachable (e.g., sandbox times out or dies)
  3. Call commands.run() — it hangs indefinitely because there is no read timeout on the HTTP stream

Additional context

There was a blip in e2b of some sort and we saw couple of our sandboxes die or timeout at the same time that a long running command had been issued; the command was retried automatically with the commands.run, but then all of those tasks in our system hung indefinitely getting stuck at commands.run.

My (claude's) best guess:
When a sandbox becomes unreachable (e.g., sandbox dies or network connectivity is lost), commands.run() hangs indefinitely because the underlying call_server_stream does not set a read timeout on the HTTP stream. The request_timeout parameter only sets connect and pool timeouts for streaming calls, unlike unary calls which correctly set all four (connect, pool, read, write).

In e2b_connect/client.py, _prepare_unary_request (used by files.make_dir, files.write, etc.) correctly sets all timeouts:

  extensions = {
      "timeout": {
          "connect": request_timeout,
          "pool": request_timeout,
          "read": request_timeout,
          "write": request_timeout,
      }
  }

But _prepare_server_stream_request (used by commands.run) omits read and write:

  extensions = {
      "timeout": {"connect": request_timeout, "pool": request_timeout}
  }

The timeout parameter is sent as a connect-timeout-ms header for server-side enforcement, but if the server is unreachable, the client never gets a response and httpcore's ConnectionPool.stream() blocks on read forever.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions