Skip to content

Fix volume SDK issues: transports, timeouts, empty files, eager stream errors#1431

Merged
mishushakov merged 2 commits into
mainfrom
mishushakov/fix-volume-sdk-issues
Jun 12, 2026
Merged

Fix volume SDK issues: transports, timeouts, empty files, eager stream errors#1431
mishushakov merged 2 commits into
mainfrom
mishushakov/fix-volume-sdk-issues

Conversation

@mishushakov

@mishushakov mishushakov commented Jun 12, 2026

Copy link
Copy Markdown
Member

Fixes a batch of review findings in the JS and Python volume SDKs, aligning behavior between the two. Python now caches AsyncVolume HTTP transports per event loop and proxy (sync per thread) instead of a process-wide singleton, applies the 60s default request_timeout to metadata operations that previously ran with httpx timeouts disabled, no longer falls back to E2B_ACCESS_TOKEN for volume content auth, and no longer mutates the caller's headers dict. JS Volume.readFile now returns empty values instead of undefined for empty files, and volume content requests get the documented 60s default request timeout. All changes are covered by new mock-based unit tests (no live API needed) plus changesets for both SDKs.

Usage examples

volume = await AsyncVolume.connect(volume_id)

# Times out after 60s by default (previously could hang indefinitely)
entries = await volume.list("/")
const volume = await Volume.connect(volumeId)

// Returns an empty Blob / ReadableStream for empty files (previously undefined)
const blob = await volume.readFile('empty.txt', { format: 'blob' })

// Times out after the documented 60s by default; pass 0 to disable
await volume.getInfo('file.txt', { requestTimeoutMs: 0 })

🤖 Generated with Claude Code

…clients

- Python: cache AsyncVolume HTTP transports per event loop (and per proxy)
  instead of a process-wide singleton; cache sync transports per thread
- Python: apply request_timeout (default 60s) to volume metadata operations
  instead of running with httpx timeouts disabled
- Python: send read_file(format="stream") request eagerly so errors raise at
  call time, matching JS
- Python: drop the E2B_ACCESS_TOKEN fallback for volume content auth and stop
  mutating the caller's headers dict in VolumeConnectionConfig
- JS: return empty Blob/ReadableStream/Uint8Array from Volume.readFile for
  empty files instead of undefined
- JS: apply the documented 60s default request timeout to volume content
  requests

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@changeset-bot

changeset-bot Bot commented Jun 12, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: dbd37fd

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

This PR includes changesets to release 2 packages
Name Type
@e2b/python-sdk Patch
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

@cursor

cursor Bot commented Jun 12, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
Python drops E2B_ACCESS_TOKEN for volume content and changes shared HTTP transport lifetime, which can break env-based auth or multi-loop usage; otherwise localized client fixes.

Overview
JS: Volume.readFile no longer returns undefined for empty files; it returns empty Uint8Array, '', Blob, or stream as appropriate. VolumeConnectionConfig now defaults requestTimeoutMs to 60s for volume content calls (overridable; 0 disables).

Python: Volume content HTTP clients apply the 60s request_timeout to httpx instead of unlimited waits. Async transports are cached per event loop and proxy; sync transports per thread and proxy. Auth uses only the volume token—E2B_ACCESS_TOKEN is not used. VolumeConnectionConfig copies caller headers instead of mutating them.

Mock-based tests cover read paths, timeouts, transport caching, and auth/config behavior in both SDKs.

Reviewed by Cursor Bugbot for commit dbd37fd. Bugbot is set up for automated code reviews on this repo. Configure here.

@github-actions

github-actions Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Package Artifacts

Built from 679ddad. Download artifacts from this workflow run.

JS SDK (e2b@2.29.2-mishushakov-fix-volume-sdk-issues.0):

npm install ./e2b-2.29.2-mishushakov-fix-volume-sdk-issues.0.tgz

CLI (@e2b/cli@2.11.2-mishushakov-fix-volume-sdk-issues.0):

npm install ./e2b-cli-2.11.2-mishushakov-fix-volume-sdk-issues.0.tgz

Python SDK (e2b==2.28.2+mishushakov-fix-volume-sdk-issues):

pip install ./e2b-2.28.2+mishushakov.fix.volume.sdk.issues-py3-none-any.whl

@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: 528e97bfe1

ℹ️ 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".

def get_transport(config: VolumeConnectionConfig) -> AsyncTransportWithLogger:
if AsyncTransportWithLogger.singleton is not None:
return AsyncTransportWithLogger.singleton
key: TransportKey = (id(asyncio.get_running_loop()), config.proxy)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Key async transport cache by loop objects

When async volume calls are made from sequential event loops (for example repeated asyncio.run(...) calls in a worker or test harness), CPython can reuse the object id of a closed loop almost immediately. Because this cache stores only id(get_running_loop()), a new loop can receive the AsyncHTTPTransport created for the previous closed loop, reintroducing the cross-loop/closed-loop transport failures this change is meant to avoid. Keying by the loop object itself, preferably with weak references, avoids stale id collisions.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's same defect as the rest of the SDK, would merge as-is and then do a follow up PR that fixes that in both. @matthewlouisbrockman for visibility

Comment thread packages/python-sdk/e2b/volume/volume_async.py Outdated
…n SDK

Drop the eager-send change so the stream request is still deferred to first
iteration; keep the stream tests but assert errors while consuming instead
of at call time.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@mishushakov mishushakov enabled auto-merge (squash) June 12, 2026 19:10
@mishushakov mishushakov merged commit 0b0c728 into main Jun 12, 2026
23 of 24 checks passed
@mishushakov mishushakov deleted the mishushakov/fix-volume-sdk-issues branch June 12, 2026 19:17
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.

2 participants