Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

A brand-new Worker Preview's Durable Objects answer internal error for seconds

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.

The code

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:

  1. wrangler preview --name repro-<t>: a brand-new preview. As soon as it returns, 10 concurrent GET / every 250 ms for --seconds (40 calls a second).
  2. wrangler preview --name repro-<t> again: the same preview redeployed in place. The same calls.
  3. wrangler preview delete, then the same calls against the parent (the control).

Expected, and what happens

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.

Run it

npm install
export CLOUDFLARE_API_TOKEN=… CLOUDFLARE_ACCOUNT_ID=…
node run.mjs --runs 3 --seconds 30

It 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.

What we saw

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, rokbalhnrte8rrq9i1nf8jre
  • repro-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.

Asks

  1. What does a new preview's Durable Object namespace wait on before it can be routed?
  2. Could wrangler preview, or the Previews API, return only once the namespace is routable, or expose a readiness signal?
  3. Please look up the reference ids above.

About

A brand-new Worker Preview's Durable Objects answer 'internal error; reference = …' for seconds after wrangler preview returns; an in-place redeploy does not

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages