You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A dev-server run of dewpt emitted a continuous stream of opaque Error: internal error; reference = <id> lines from workerd, with no attributable HTTP request and no stack. It was isolated to sessions in which the field surface (/) had been loaded, and did not reproduce on a server exercising only /board. After this issue, we know what throws, whether it costs metered Workers AI calls, and either it is fixed or it is a documented known-benign condition. Today it is an unexplained recurring error in the default surface of the app.
Context
Observed 2026-08-08 while browser-verifying #61. Deliberately not attributed to that PR, and here is the isolation evidence:
Every /api/board/* response in the same window was 2xx.
None of the errors carried BoardDO's own signatures — board pump failed, hop failed, station prepare failed — which are the strings the board's own catch blocks emit as JSON.
A freshly restarted dev server that loaded only/board, ran a full lineage lifecycle to the edge with real Workers AI generation, and evaporated it, produced zero errors.
The errors appeared only in the earlier server instance, which had also loaded / (the field surface) — which creates a SessionDO, preseeds, and runs its own pool pump on an alarm loop, independently of whether any client is still connected.
That last point is the leading hypothesis and nothing more: the shape (recurring, no request line, no stack) is consistent with a throw inside an alarm handler or a remote-binding transport fault, and env.AI is bound remote in local dev. It has not been confirmed, and I did not diagnose it.
Why it matters beyond noise: if the source is SessionDO's pool pump throwing and retrying, each cycle may be a metered Workers AI call against a live account, burning quota for a tab nobody has open. That would make this a cost bug rather than a logging annoyance. It may equally be a benign local-dev artifact of the remote-binding proxy. Both are plausible; neither is established.
Reproduction
npm run dev (or preview_start with the dewpt config in .claude/launch.json).
Load http://localhost:8787/ — the field surface — and let it initialise.
Navigate away to http://localhost:8787/board/, or simply leave the server running.
Watch the wrangler output.
Expected: no errors, or errors that name what failed.
Actual: a repeating stream of ✘ [ERROR] Error: internal error; reference = <random id> with no request line, no stack, and no JSON payload. Interleaved with successful 200 OK request lines for unrelated routes.
Environment: wrangler 4.111.0, macOS (darwin 25.5.0), local dev with env.AI bound remote, Node via the repo's toolchain. Not observed in production — nobody has looked.
Pointers
src/session-do.ts — the field's Durable Object; its alarm() and pool pump are the leading suspect
src/board/board-do.ts:558 — the board's alarm(), whose catch logs board pump failed; the pattern to compare against, and the reason we can say the board is not the source
src/generation.ts — embedTexts / expandPole; these throw on transient AI faults, and where those throws land is the question
src/index.ts — /api/debug/ai, the existing probe (returned ok, 635ms, 1024 dims throughout, so the binding was healthy)
public/app.js, public/preseed.js, public/preseed-pool.js — what the field kicks off on load
wrangler.jsonc — the AI binding's remote mode
CLAUDE.md — the WARP and Cloudflare Access traps, both of which produce different symptoms and should be ruled out first
Do not silence it with a broad catch. An unexplained error that stops printing is strictly worse than one that prints.
If the fix is a catch, it must log something that names the operation, matching the JSON.stringify({ level, message, ... }) shape already used in board-do.ts and session-do.ts.
Reproduce before changing anything — this may be a local-dev artifact of the remote-binding proxy and not a code defect at all, in which case the deliverable is documentation, not a patch.
Rule out the two known local traps first (WARP blocking workerd egress; Cloudflare Access on the workers.dev domain). Both are in CLAUDE.md and both masquerade as app bugs.
Any AI calls made while investigating are metered: state and cap the expected number before running a loop.
Acceptance criteria
The throwing code path is named, with a file and line — or it is established that the error originates outside our code, with the evidence for that.
It is stated whether each occurrence costs a Workers AI call, and roughly at what rate.
Either the error no longer appears in a normal dev session, or CLAUDE.md gains an entry describing it as known-benign alongside the WARP and Access traps, so the next person does not re-investigate it.
No new broad catch that hides an error without logging it.
Out of scope
Anything on the /board surface — it was shown clean in isolation.
The 7 Dependabot advisories on the default branch; unrelated, separate track.
Refactoring SessionDO beyond what diagnosing this requires.
Reasoning guidance
Think carefully and step-by-step; this is harder than it looks. The error is anonymous by construction, so the work is mostly building an attribution method — bisecting which surface triggers it, and instrumenting the alarm paths — rather than reading code until the answer appears.
Task
A dev-server run of dewpt emitted a continuous stream of opaque
Error: internal error; reference = <id>lines from workerd, with no attributable HTTP request and no stack. It was isolated to sessions in which the field surface (/) had been loaded, and did not reproduce on a server exercising only/board. After this issue, we know what throws, whether it costs metered Workers AI calls, and either it is fixed or it is a documented known-benign condition. Today it is an unexplained recurring error in the default surface of the app.Context
Observed 2026-08-08 while browser-verifying #61. Deliberately not attributed to that PR, and here is the isolation evidence:
/api/board/*response in the same window was 2xx.board pump failed,hop failed,station prepare failed— which are the strings the board's own catch blocks emit as JSON./board, ran a full lineage lifecycle to the edge with real Workers AI generation, and evaporated it, produced zero errors./(the field surface) — which creates aSessionDO, preseeds, and runs its own pool pump on an alarm loop, independently of whether any client is still connected.That last point is the leading hypothesis and nothing more: the shape (recurring, no request line, no stack) is consistent with a throw inside an alarm handler or a remote-binding transport fault, and
env.AIis boundremotein local dev. It has not been confirmed, and I did not diagnose it.Why it matters beyond noise: if the source is
SessionDO's pool pump throwing and retrying, each cycle may be a metered Workers AI call against a live account, burning quota for a tab nobody has open. That would make this a cost bug rather than a logging annoyance. It may equally be a benign local-dev artifact of the remote-binding proxy. Both are plausible; neither is established.Reproduction
npm run dev(orpreview_startwith thedewptconfig in.claude/launch.json).http://localhost:8787/— the field surface — and let it initialise.http://localhost:8787/board/, or simply leave the server running.Expected: no errors, or errors that name what failed.
Actual: a repeating stream of
✘ [ERROR] Error: internal error; reference = <random id>with no request line, no stack, and no JSON payload. Interleaved with successful200 OKrequest lines for unrelated routes.Environment: wrangler 4.111.0, macOS (darwin 25.5.0), local dev with
env.AIboundremote, Node via the repo's toolchain. Not observed in production — nobody has looked.Pointers
src/session-do.ts— the field's Durable Object; itsalarm()and pool pump are the leading suspectsrc/board/board-do.ts:558— the board'salarm(), whosecatchlogsboard pump failed; the pattern to compare against, and the reason we can say the board is not the sourcesrc/generation.ts—embedTexts/expandPole; these throw on transient AI faults, and where those throws land is the questionsrc/index.ts—/api/debug/ai, the existing probe (returnedok, 635ms, 1024 dimsthroughout, so the binding was healthy)public/app.js,public/preseed.js,public/preseed-pool.js— what the field kicks off on loadwrangler.jsonc— theAIbinding'sremotemodeCLAUDE.md— the WARP and Cloudflare Access traps, both of which produce different symptoms and should be ruled out firstConstraints
catch. An unexplained error that stops printing is strictly worse than one that prints.catch, it must log something that names the operation, matching theJSON.stringify({ level, message, ... })shape already used inboard-do.tsandsession-do.ts.workers.devdomain). Both are in CLAUDE.md and both masquerade as app bugs.Acceptance criteria
CLAUDE.mdgains an entry describing it as known-benign alongside the WARP and Access traps, so the next person does not re-investigate it.catchthat hides an error without logging it.Out of scope
/boardsurface — it was shown clean in isolation.SessionDObeyond what diagnosing this requires.Reasoning guidance
Think carefully and step-by-step; this is harder than it looks. The error is anonymous by construction, so the work is mostly building an attribution method — bisecting which surface triggers it, and instrumenting the alarm paths — rather than reading code until the answer appears.