@cloudflare/shell@0.3.3
cloudflare/agents@cloudflare/shell@0.3.3Apr 18, 2026by github-actions[bot]
AI Summary
This patch makes `Workspace` idempotent on duplicate construction for the same `{sql, namespace}` when storage options (`r2`, `r2Prefix`, `inlineThreshold`) agree. It fixes issues with Vite HMR re-evaluating Durable Object modules and helpers constructing short-lived Workspaces alongside existing ones. The guard is preserved to catch actual bugs when storage options diverge.
Key Highlights
- Workspace now allows duplicate construction for the same namespace when storage options agree
- Fixes Vite HMR issues where Durable Object modules are re-evaluated against still-live ctx.storage.sql
- Preserves error throwing when storage options (r2, r2Prefix, inlineThreshold) actually differ
- Error messages now name the disagreeing field and both values for easier debugging
- onChange is intentionally excluded from consistency checks as each instance calls its own listener
Full Release Notes
### Patch Changes
- [#1333](https://github.com/cloudflare/agents/pull/1333) [`dce4d17`](https://github.com/cloudflare/agents/commit/dce4d17b5f386ea9adcb5f602be78bb7d7ed83d8) Thanks [@threepointone](https://github.com/threepointone)! - `Workspace` is now idempotent on duplicate construction for the same `{sql, namespace}` when the options that affect durable storage (`r2`, `r2Prefix`, `inlineThreshold`) agree. Previously, any second construction threw `Workspace namespace "<ns>" is already registered on this agent`, which wedged legitimate cases — most commonly Vite HMR re-evaluating a Durable Object's module against a still-live `ctx.storage.sql`, and helpers that accept a `sql` and construct a short-lived `Workspace` alongside an existing class-field one.
The guard is preserved where it actually catches a bug: if a second construction passes a different `r2`, `r2Prefix`, or `inlineThreshold`, the constructor throws with a message naming the disagreeing field and both values — because diverging storage options silently route large files to different R2 keys or classify them at different sizes, so reads through one instance would fail to find data written via the other.
`onChange` is intentionally not part of the consistency check — each `Workspace` instance calls its own listener for its own writes, which is the existing per-instance semantic.