Skip to content

Releases: cloudflare/sandbox-sdk

@cloudflare/sandbox@0.9.2

29 Apr 13:48
48c0bf3

Choose a tag to compare

Patch Changes

  • #645 2d0687b Thanks @scuffi! - Fix createBackup() excludes that use gitignore-style ** globstars.

    Normalize globstar excludes to the mksquashfs-compatible patterns used by the backup pipeline so local and production backups handle them consistently.

@cloudflare/sandbox@0.9.1

27 Apr 19:20
ea69312

Choose a tag to compare

Patch Changes

  • 51f1d04 Thanks @whoiskatrin! - Coalesce concurrent Sandbox.destroy() calls onto a single teardown. If a
    previous destroy() is still in flight, subsequent calls await the same
    underlying work instead of starting a second teardown, and emit a canonical
    sandbox.destroy.coalesced event per coalesced call for observability.
    Once the in-flight teardown settles, later destroy() calls run a fresh
    teardown as before. Fixes observed destroy-recreate thrash where external
    health checks can invoke destroy() faster than the sandbox can initialize.

  • #592 b2bf021 Thanks @whoiskatrin! - Add sandbox.getContainerPlacementId() to retrieve the Cloudflare placement ID
    observed for the underlying container.

    The placement ID identifies the current container placement and changes when
    the container is replaced by the platform. Compare the returned value against
    a stored value to detect container replacement and trigger reconciliation.

    The placement ID is captured during the session-create handshake and cached
    in Durable Object storage, so reads are cheap and do not require a healthy
    container. A fresh placement ID is captured on each subsequent handshake,
    so a replacement is reflected the next time the sandbox is used.

    Returns undefined when no session-create handshake has been observed yet on
    this sandbox — call any method that triggers session creation (such as
    exec()) first. Returns null when a handshake has completed but the
    container's CLOUDFLARE_PLACEMENT_ID environment variable is not set, such as
    in local development with wrangler.

    await sandbox.exec('true'); // ensures the handshake has run
    const containerPlacementId = await sandbox.getContainerPlacementId();
    if (
      typeof containerPlacementId === 'string' &&
      containerPlacementId !== lastKnownPlacementId
    ) {
      // Container was replaced — reconcile state
    }

@cloudflare/sandbox@0.9.0

24 Apr 17:24
e6ef054

Choose a tag to compare

Minor Changes

  • #633 4e628ae Thanks @whoiskatrin! - Handle shell exits with SessionTerminatedError, and let the same session id recover on the next call.

    import { SessionTerminatedError } from '@cloudflare/sandbox';
    
    const session = await sandbox.createSession({ id: 'build' });
    
    try {
      await session.exec('exit 42');
    } catch (error) {
      if (error instanceof SessionTerminatedError) {
        console.log(error.exitCode); // 42
        await session.exec('echo fresh shell');
      }
    }

    If a session's shell exits, the failing call now returns SESSION_TERMINATED
    (HTTP 410) with the observed exit code instead of a generic internal error.
    Retrying with the same session id, or calling createSession({ id }), starts a
    fresh session without destroying the whole sandbox. Session-local state such as
    the working directory, environment variables, shell functions, and background
    jobs is lost when the shell exits.

@cloudflare/sandbox@0.8.14

24 Apr 08:23
f5843e7

Choose a tag to compare

Patch Changes

  • #613 174313f Thanks @ghostwriternr! - Avoid duplicate session-create calls when parallel operations hit a
    fresh sandbox. Parallel callers now share one setup call instead of
    each issuing their own. Sequential operations are unaffected.

    Session setup also now retries cleanly on the next operation if it is
    interrupted partway through — including by a container stop during
    first use — instead of leaving the sandbox in a state that looks
    initialized but references a session the container no longer has.

  • #624 bbdfd95 Thanks @ghostwriternr! - Fix sandboxes staying alive past their configured sleepAfter value.

    Workers that passed configuration options to getSandbox() on every request (sleepAfter, keepAlive, or containerTimeouts) could unintentionally extend sandbox lifetimes. The SDK's internal reapply path treated identical reapplied values as activity, resetting the sleep timer each time. Under sustained traffic, sandboxes would never sleep at all.

    After updating, reapplying the same configuration value is a true no-op. Your getSandbox() calls continue to work exactly as before; sandboxes now respect their configured sleep timers regardless of how often configuration is reapplied.

    This release also removes the unused baseUrl option from SandboxOptions, along with the setBaseUrl RPC method on the Sandbox Durable Object. The option had no effect on runtime behavior; preview URLs are driven by the hostname passed to preview-URL APIs. If you were setting baseUrl on getSandbox(), you can safely remove it. Directly invoking the undocumented setBaseUrl RPC method will now error.

  • #629 34e3a96 Thanks @aron-cf! - Improve reliability of desktop.stop() as well as general isolation of the desktop processes by
    running them in a subprocess. This should ensure that processes are cleaned up when calling
    desktop.stop() and crashes should not impact the sandbox container service.

  • #576 9222fd0 Thanks @whoiskatrin! - Fix stream controller race condition causing "Invalid state: Controller is already closed" errors

    Resolves an issue where client disconnections during streaming operations could cause unhandled TypeError exceptions, potentially corrupting the SDK bridge state. The fix adds defensive error handling in the execute streaming handler to gracefully handle callbacks firing after stream cancellation.

  • #614 74a58e9 Thanks @aron-cf! - Adds a new transport: 'http' | 'websocket' field to the getSandbox() options. This can be
    used to dynamically select transport on a per-sandbox basis.

    [!NOTE]
    Changing transport on an already existing sandbox may result in dropped connections, it is
    recommended to keep the same transport for the lifetime of the sandbox instance.

    const sandbox = getSandbox(env.Sandbox, 'my-sandbox', {
      transport: 'websocket'
    });
  • #567 1c7337a Thanks @scuffi! - Adds support for local backup and restore through the BACKUP_BUCKET R2 binding in local development when localBucket: true is set.

@cloudflare/sandbox@0.8.11

15 Apr 16:43

Choose a tag to compare

Patch Changes

  • #585 ab84333 Thanks @aron-cf! - Add the sandbox bridge — an HTTP API that translates REST calls into Sandbox Durable Object operations. Deploy the bridge as a standalone Cloudflare Worker to expose session management, command execution, file read/write, PTY, and workspace mount/unmount over HTTP. Includes an optional warm pool Durable Object for pre-provisioning sandboxes to reduce cold-start latency.

    Import the bridge factory and warm pool from @cloudflare/sandbox/bridge.

    import { bridge } from '@cloudflare/sandbox/bridge';
    export { Sandbox } from '@cloudflare/sandbox';
    export { WarmPool } from '@cloudflare/sandbox/bridge';
    
    export default bridge({
      fetch(request, env, ctx) {
        // your code here
        return new Response('OK');
      }
    });

@cloudflare/sandbox@0.8.10

13 Apr 18:10
da489d3

Choose a tag to compare

Patch Changes

  • #577 a56898c Thanks @whoiskatrin! - Improve backup restores by mounting backup archives from R2 during restore
    instead of downloading them into local container storage first.

@cloudflare/sandbox@0.8.9

10 Apr 12:47
a91e292

Choose a tag to compare

Patch Changes

  • #570 8363119 Thanks @aron-cf! - Fix unmountBucket() silently succeeding when the FUSE filesystem fails to unmount. The method now checks the fusermount exit code and throws BucketUnmountError on failure, cleans up the mount directory after a successful unmount, and the container image includes the /etc/mtab symlink that fusermount requires.

  • #573 cc14fc7 Thanks @whoiskatrin! - Increase the default gitCheckout() clone timeout to 10 minutes so larger repositories and slower Git remotes do not fail after 2 minutes by default.
    You can now override the git clone subprocess timeout per call with the cloneTimeoutMs option when a checkout needs more time.

@cloudflare/sandbox@0.8.8

09 Apr 21:53
3f57230

Choose a tag to compare

Patch Changes

  • #571 c5db840 Thanks @whoiskatrin! - Require @cloudflare/containers 0.3.0 so sandbox apps pick up the latest Containers platform updates.

@cloudflare/sandbox@0.8.7

08 Apr 16:25
37b6805

Choose a tag to compare

Patch Changes

  • #565 ffcbd3a Thanks @whoiskatrin! - Require @cloudflare/containers 0.2.3 or newer.

  • #550 1db32ea Thanks @scuffi! - Setting interceptHttps = true on your Sandbox will now automatically trust the Cloudflare-injected CA certificate at container startup, enabling outbound HTTPS traffic interception.

@cloudflare/sandbox@0.8.6

07 Apr 16:07
6cb59e0

Choose a tag to compare

Patch Changes

  • #557 f17045b Thanks @AshishKumar4! - Fix startup deadlock when using WebSocket transport.

    Sandboxes that call exec() or other SDK methods inside onStart() could
    get stuck in an infinite timeout loop, requiring a restart. This is now
    handled automatically.