ReleaseCoreWeaveCoreWeavepublished Jun 9, 2026seen 1d

coreweave/cwsandbox-client v0.25.0

coreweave/cwsandbox-client

Open original ↗

Captured source

source ↗
published Jun 9, 2026seen 1dcaptured 1dhttp 200method plain

v0.25.0

Repository: coreweave/cwsandbox-client

Tag: v0.25.0

Published: 2026-06-09T19:46:25Z

Prerelease: no

Release notes:

v0.25.0 (2026-06-09)

_This release is published under the Apache-2.0 License._

Bug Fixes

  • files: Address review feedback on large-file handling (`9396d21`)

Resolves the review on PR #133. Eight findings from @djenriquez, by severity:

Blockers:

  • Truncation false-positive (read_file auto-fallback). _verify_no_truncation statted the file *after* the read, so a file appended to between cat's EOF and the stat made expected exceed what was legitimately delivered and raised a spurious truncation error — on the default read_file() 32–256 MiB fallback, where in prod this check is the only truncation defense and the false positive sits on the critical path (e.g. read_file('/var/log/app.log') on a live log). Now the file's size is captured *before* the read: the read_file fallback feeds the server-reported pre-read size straight in (no extra stat round-trip), and read_file_streaming stats once up front. A concurrent append only grows the delivered count, so it can no longer look like a short read. The inverted docstring justification is corrected.
  • stat timeout overshoot. The stat used the original caller budget, so a 600s read that spent 599s streaming could spend up to 10s more on the stat and blow past the deadline (the comment/docstring claimed otherwise). The streaming read now tracks an absolute monotonic deadline at op start; the pre-read stat draws from the *remaining* budget capped at STAT_INTEGRITY_TIMEOUT_SECONDS, and the read gets what's left.
  • Sync iterable on the event loop. _write_file_streaming_async consumed a sync iterable by calling next() directly on the shared background loop, so a blocking source (file handle, NFS/FUSE read, network generator) stalled every other operation on that loop. Each next() (and chunk coercion) now runs in the default executor via a small async generator; the iterator advances one step per consumed item, so no prefetch buffer or hand-off race is needed and the downstream exec stdin queue still provides backpressure. The TypeError contract for bad chunks is preserved (raised in the worker, re-raised unchanged).
  • Observed cap not clamped. _record_observed_cap cached the server cap with no upper bound and the old frame-safe limit had been deleted, so a cluster reporting a cap near/above the 100 MiB gRPC frame ceiling would route a sub-cap payload to the unary path and hit a frame-size reject. Restored MAX_FILE_UNARY_BYTES (channel limit − 1 MiB framing headroom) and clamp the effective cap to it in _file_op_cap; anything above streams instead.

Reason split:

  • CWSANDBOX_FILE_TOO_LARGE covered two opposite conditions — a size-policy refusal (no data lost, switch to streaming) and a post-hoc short read (data lost, already streaming, "use read_file_streaming" is a no-op). Split the truncation case into its own CWSANDBOX_FILE_TRUNCATED reason while it is still unreleased (free now, breaking later).

Reviewer questions, resolved:

  • STREAM_BACKPRESSURE no longer rides on .reason (the AIP-193 namespace). It now has its own .stream_code attribute on SandboxStreamBackpressureError; .reason is None there. The class remains the discriminator and existing except SandboxExecutionError handlers are unaffected.
  • The streaming-read integrity check is gated by size band (TRUNCATION_CHECK_MIN_BYTES): silent truncation is a large-payload phenomenon, so below the band the pre-read stat is skipped entirely. The read_file fallback pays no stat at all (it reuses the server-reported size).

Docs:

  • read_file's docstring no longer over-promises that all >256 MiB reads are refused: when the backend signals via resource exhaustion rather than a sized CWSANDBOX_FILE_TOO_LARGE the client can't know the remote size, so a very large file can still be buffered — callers are pointed at read_file_streaming. (The uncapped-buffer OOM on that branch is pre-existing and tracked separately.)

ruff + mypy clean; full unit suite green (1171 tests, +9 new covering the pre-read baseline, growing-file no-false-positive, frame-safe clamp, sync-iter executor offload, remaining-budget stat timeout, band gating, and stream_code).

Chores

  • Add djenriquez and brandonrjacobs as codeowners (`ae523d5`)

Co-Authored-By: Claude Opus 4.8 (1M context)

Documentation

Adds examples/large_file_streaming.py demonstrating how to stream large files without tripping backpressure, and registers it in examples/README.md.

The example shows:

  • the fast-drain read loop (read_file_streaming into a local file with only the

write inline) that keeps up with the producer;

  • the slow-inline-work anti-pattern that overruns the buffer and raises

SandboxStreamBackpressureError, clearly labeled as what NOT to do;

  • catching that error and recovering with the fast-drain pattern (it is not

retryable as-is — the read pace must be fixed, or the work chunked, first).

  • Keep streaming guidance free of internal implementation detail (`23036ef`)

Scrub the user-facing read_file_streaming docstring and the large-file streaming example of implementation wording that doesn't belong in the public SDK surface: drop the internal queue-size constant name and "server frame size" mechanics, and reword "the stream's buffer fills and the server ends it" to describe the observable behavior (output produced faster than it's read; the stream is ended early). The actionable guidance — keep the read loop tight, move slow work off it, memory grows with how far behind you fall — is retained.

No behavior change; docstring/comment wording only.

Features

  • Surface truncated exec output as a typed error (`8c910cf`)

When a command runs to completion but some of its output is lost in transit, the server now ends the stream with a STREAM_TRUNCATED error instead of returning partial output alongside a success exit code. Map it to a new typed…

Excerpt shown — open the source for the full document.

Notability

notability 3.0/10

Routine client library version update.