When you create a Worker Preview with wrangler preview, you expect its Durable Objects to answer
as soon as the command returns and the preview URL serves. For the first seconds, sometimes up to
about 25 s, a Durable Object call from the preview's own Worker fails with workerd's opaque
internal error; reference = …. Deploying the same preview again in place does not do this, and
the parent Worker almost never does. It happened to 8 of 12 brand-new previews in our first runs
on 2026-09-24, and to 3 of 3 with this repo as it is.
src/index.js is the whole Worker: one SQLite-backed Durable Object class, Pinger, bound as
PINGER in the Worker and in previews.durable_objects. Each request calls a Durable Object that
never existed:
await env.PINGER.getByName(crypto.randomUUID()).ping(); // returns "pong"
return Response.json({ ok: true, ms });
// on a throw: Response.json({ ok: false, error: error.message, ms }, { status: 500 })run.mjs deploys the parent Worker fresh-preview-repro (idempotent), then does this for each run:
wrangler preview --name repro-<t>: a brand-new preview. As soon as it returns, 10 concurrentGET /every 250 ms for--seconds(40 calls a second).wrangler preview --name repro-<t>again: the same preview redeployed in place. The same calls.wrangler preview delete, then the same calls against the parent (the control).
Expected, every phase: every call answers { "ok": true }.
A brand-new preview, then the same preview redeployed in place (real lines from this repo, 2026-09-24 17:36 UTC, wrangler 4.138.0):
{"run":1,"name":"repro-muftcjv5","phase":"new","calls":1200,"failed":33,"lastFailureMs":6324,"perFiveSeconds":"31 2 0 0 0 0","internalError":{"count":33,"firstMs":33,"lastMs":6324,"samples":["500 {\"ok\":false,\"error\":\"internal error; reference = s6uafjs9jo4v5hq5faqacuiu\",\"ms\":493}", …]}}
{"run":1,"name":"repro-muftcjv5","phase":"redeployed","calls":1200,"failed":0,"perFiveSeconds":"0 0 0 0 0 0"}
perFiveSeconds is the failed calls in each 5 s since wrangler preview returned. Each failure is
the stub call throwing internal error; reference = …, caught in the fetch handler, about 500 ms
after the call started.
npm install
export CLOUDFLARE_API_TOKEN=… CLOUDFLARE_ACCOUNT_ID=…
node run.mjs --runs 3 --seconds 30It prints one JSON line per phase: the calls, the failed ones per 5 s, when the first and last
failure came, and up to three samples of each kind (internalError, notRoutedYet for a 404 from a
preview URL not yet routed, other). The parent Worker stays deployed; each preview is deleted at
the end of its run.
2026-09-24, account 376ef7ed81b0573f93524de763666c15, from a laptop in London and a Depot runner
in IAD, with wrangler 4.105.0 built from workers-sdk PR #14416:
| phase | failed this way | how |
|---|---|---|
| brand-new preview | 8 of 12 | 97–519 calls each answered 500 internal error; reference = …, from the first call until 4–24 s after wrangler preview returned |
| redeployed in place | 0 of 10 | the only failures were Durable Object reset because its code was updated., which a redeploy is expected to cause |
| parent | 1 call in about 30,000 |
Reference ids from those runs:
repro-mufcaq2b(created about 09:38:49Z):ja4986b98df936tljft4kmt2,rokbalhnrte8rrq9i1nf8jrerepro-mufcmir2(about 09:47:59Z):f0oovaafljltm8m3a6v4gbuo,anat2tnh9g6vsj5mc0tttc1t
2026-09-24 17:36–17:41 UTC, the same account, from a laptop in London, with this repo as it is
(released wrangler 4.138.0). observed-2026-09-24.txt has every line.
| run | preview | brand-new: failed of 1,200 | last failure | redeployed in place | parent |
|---|---|---|---|---|---|
| 1 | repro-muftcjv5 |
33, all internal error (31 in the first 5 s) |
+6.3 s | 0 | 1 client timeout |
| 2 | repro-muftey7u |
2, both internal error |
+0.8 s | 0 | 0 |
| 3 | repro-mufth5q0 |
141, all internal error (118 in the first 5 s) |
+8.5 s | 2 × Durable Object reset because its code was updated. |
0 |
All three brand-new previews failed this way; none of the in-place redeploys or parent phases did.
Reference ids: s6uafjs9jo4v5hq5faqacuiu, h243a8q25gio78mtue5d32e9 (run 1),
h40rsah4nobnvlvj1ghc04t5, 07luk1mtimnb5dcpndlqljvl (run 2), fb3nookr9kr3m4o32c7rot35,
b5pshvpgdp9427lujoleka25 (run 3).
The same fault in a real application: on previews of our own platform Worker, Workers Logs shows no Durable Object invocation for the failing calls, so they fail before any Durable Object runs. In CI it failed whole end-to-end runs: 139 of 145 failed attempts in one run were this error, all within 8 s, 16–24 s after the deploy.
- What does a new preview's Durable Object namespace wait on before it can be routed?
- Could
wrangler preview, or the Previews API, return only once the namespace is routable, or expose a readiness signal? - Please look up the reference ids above.