e2b-dev / e2b-dev/E2B

[Bug]: reattached stdout stream stalls after auto-resume (regression in python-sdk 2.29.1)

Open
#1,587 5 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug sdk
Dominant language
Python
Stars
13.9k
Forks
1k
Avg merge
1d 20h
Merged PRs (30d)
70

Description

Summary

After a sandbox auto-pauses and resumes, reattaching to an existing
long-lived background process via commands.connect(pid) produces a
stdout stream that intermittently delivers its first response and then
goes silent — the on_stdout callback stops firing for subsequent
responses even though the process is still running and still writing.

This is a regression introduced in python-sdk 2.29.1 and present in
every release since (through 2.34.0). The likely change is cb061d2
("Fix several command and PTY streaming issues"), which reworked
incremental stdout/stderr decoding and stream-connection teardown.

Bisect (strong evidence)

Identical workload, same account/templates; only the SDK version changed.
The workload is a real stdio server (@modelcontextprotocol/server-everything
over npx) driven through repeated pause → resume → commands.connect(pid)
reattach cycles. "Stall rate" = fraction of reattach cycles where the
reconnected stdout stream failed to deliver a complete response, over 6
cycles:

Version Stall rate
2.20.2 1/6
2.21.0 1/6
2.27.0 1/6
2.29.0 1/6 ← last good
2.29.1 6/6 ← first bad
2.30.0 6/6
2.34.0 6/6

The transition is sharp and clean: every version up to and including
2.29.0 stalls ~1/6; every version from 2.29.1 on stalls ~6/6. The only
command/stream change in 2.29.1 is cb061d2.

Reproduction conditions

The stall reproduces reliably only through a realistic streaming
workload
— a long-lived process reattached after resume that answers
several requests with sizeable, multi-chunk stdout responses (in
our case JSON-RPC tools/list / resources/list / prompts/list from an
stdio MCP server). The pattern observed: the first response after reattach
arrives, later ones never do.

A trivial synthetic process (one small line per second, or a single large
one-shot write) does not isolate the regression — those either stream
fine on both versions, or hit an unrelated single-write truncation that is
version-independent. So the reliable repro is the real stdio-server flow
above; we can share the exact harness on request.

Expected vs actual

  • Expected (≤ 2.29.0): after reattach, on_stdout keeps firing for
    every subsequent response; a full multi-request refresh completes.
  • Actual (≥ 2.29.1): after reattach, the stream delivers the first
    response (sometimes partially) then goes silent; subsequent responses
    never arrive, while a fresh reconnect shows the process still alive.

Impact

Any workload relying on a long-lived background process surviving
auto-pause and being reattached after resume (e.g. an stdio server behind
a gateway) loses output on nearly every resume from 2.29.1 on, forcing a
full fresh-sandbox rebuild as a workaround. On 2.29.0 this was rare
(~1/6); from 2.29.1 it is effectively every resume.

Environment

  • python-sdk 2.29.1 first bad, confirmed through 2.34.0; 2.29.0 last good
  • AsyncSandbox.create(lifecycle={"on_timeout": "pause", "auto_resume": True})
  • Reattach via AsyncSandbox.connect(sandbox_id=...) + commands.connect(pid=...)
  • Suspected change: cb061d2 (incremental stdout/stderr decode + stream teardown)

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by examining the Python SDK paths behind AsyncSandbox.connect(), commands.connect(pid), and the stdout callback stream, comparing the changes in cb061d2 with version 2.29.0. Reproduce the pause, resume, and reattach cycle using the realistic multi-request stdio server workload described in the issue. Done means on_stdout continues delivering complete responses after reattachment on affected SDK versions.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
api, backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.