cloudflare / cloudflare/sandbox-sdk

STALE_PREVIEW_URL on every preview request despite healthy container (0.11.0)

Open
#829 2 comments 0 reactions 1 assignee Claimed by @ghostwriternr View on GitHub
bug
Dominant language
TypeScript
Stars
1.1k
Forks
114
Avg merge
22h 42m
Merged PRs (30d)
14

Description

## Summary

`sandbox.exposePort()` succeeds (its `assertActive(runtime)` passes), but every request to the returned preview URL returns `410 STALE_PREVIEW_URL` ("Preview URL is stale because the sandbox runtime is not active") — even while the same sandbox's container is verifiably healthy and serving traffic.

## Environment

- `@cloudflare/sandbox` 0.11.0 (worker-side and DO)
- Container image: `cloudflare/sandbox:0.11.0-desktop`
- Worker deployed with a wildcard route (`*.example.com/*`) + `run_worker_first: true`; `proxyToSandbox` middleware intercepts preview hostnames
- Sandbox accessed via `getSandbox(env.Sandbox, taskId)` (also tried `{ keepAlive: true }`)

## Repro

1. Custom domain worker; wildcard DNS exists and TLS is valid (one level under the zone apex).
2. `const sandbox = getSandbox(env.Sandbox, id);`
3. `const { url } = await sandbox.exposePort(6080, { hostname: "example.com" })` → returns `https://6080--.example.com/` (HTTP 200).
4. `GET vnc.html` → `410 {"error":"Preview URL is stale because the sandbox runtime is not active","code":"STALE_PREVIEW_URL"}`.

The stale response persists for 4+ minutes of polling and across repeated `exposePort()` re-registrations (same token returned each time). `keepAlive: true` does not change it.

## Expected

Preview URL forwards to the container port once the container is running.

## Notes

- The same sandbox executes commands fine via `exec` (container boots, agent responds), so the runtime is active in practice.
- From reading the DO code, `fetchPreviewIfRunning` returns stale when `!container?.running || state.status !== "healthy"` or `!currentRuntime.isActive(runtime)`. Since `exposePort()`'s `assertActive(runtime)` passes, the registration-side state disagrees with the proxy-side state somewhere (possibly a runtime-id mismatch after DO migration/restart, or the health gate never reaching `healthy` on the desktop image).
- Same behavior with the SDK's `getDesktopStreamUrl(hostname)` convenience on the desktop image.
- Happy to provide a minimal repro repo if useful.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.