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
{{ message }}
Repository navigation
codeSplitters live: email sign-in (and sometimes sign-up, admin limits) hangs on the Worker #333
Found while testing #284 on the live Worker (codesplitters.notryanquinn.workers.dev), 2026-10-10 around 11:00 to 11:15 UTC.
Some requests never answer. The client gives up and wrangler tail logs them as canceled, with no logs or exceptions:
POST /api/auth/sign-in/email for an existing email account hangs every time (5 out of 5 tries, cut off at 15s each). The same call with an unknown email answers 401 INVALID_EMAIL_OR_PASSWORD in about 0.3s.
POST /api/auth/sign-up/email sometimes hangs (60s and 40s with no answer) and sometimes answers in under a second. The hung ones never wrote a user row.
Later, GET /api/admin/limits (signed in as admin) hung too (cut off at 10s and 15s). /api/session, /api/levels and /api/jobs in the same tab answered in about 200ms.
D1 isn't slow: direct queries take under 1ms, and the tables are small (19 limit_hits rows, 4 sessions).
Guesses, not checked: password hashing (scrypt in better-auth 1.7.7) never finishing on Workers, or a pending promise held at isolate level (the authFor WeakMap, or the module-level cache in limits.ts) that later requests wait on.
Effect: email accounts can't sign back in, so a non-admin email account can't be used for live testing. It blocks the rest of #284.
More findings, 2026-10-10. I couldn't find the cause, so this goes to Fable.
It comes and goes. All times UTC:
10:54 sign-up OK. 10:59 to 11:20: sign-up, sign-in for existing accounts and GET /api/admin/limits hang.
11:25 to 11:26: everything works (sign-in 401/200 in 0.4s, digs, queue, reset).
From 11:28: sign-in hangs again, and now unknown emails hang too (earlier they got 401 fast).
wrangler tail shows only outcome: canceled, with no logs or exceptions. D1 queries run directly answer in under 1ms.
Ruled out:
node:crypto scrypt (what better-auth 1.7.7 uses on workerd, N=16384 r=16) alone in local workerd, compat date 2026-06-01 with nodejs_compat: 30 to 60ms, no hang.
The full app in wrangler dev (local D1, no EMAIL, no containers or Artifacts): 3 sign-ups and 3 sign-ins, all fine.
What the hanging routes share: sign-in and sign-up run limit() → rules(env) → limit_hits upsert before Better Auth, and GET /api/admin/limits also calls rules(env) and reads limit_hits. /api/session, /api/levels and /api/jobs don't, and they stayed fast. That's worth checking first. Both hang windows came right after digs (Artifacts imports) at 11:04 and 11:26, so a dig may leave something stuck in the isolate.
Next step, suggested: deploy with timing logs around rules(), hit() and authFor().handler(), reproduce (dig, then sign in), and read wrangler tail.
Blocks the last step of #284 (the cron replay of a queued dig after the tab closes).
Found the cause and fixed it in #337, so it doesn't need Fable after all: one Better Auth instance per isolate shared Kysely's connection mutex across requests, and a cancelled request left the lock held.
Activity
QuinnsCode commentedon Oct 10, 2026
More findings, 2026-10-10. I couldn't find the cause, so this goes to Fable.
It comes and goes. All times UTC:
GET /api/admin/limitshang.wrangler tailshows onlyoutcome: canceled, with no logs or exceptions. D1 queries run directly answer in under 1ms.Ruled out:
node:cryptoscrypt (what better-auth 1.7.7 uses on workerd, N=16384 r=16) alone in local workerd, compat date 2026-06-01 with nodejs_compat: 30 to 60ms, no hang.wrangler dev(local D1, no EMAIL, no containers or Artifacts): 3 sign-ups and 3 sign-ins, all fine.What the hanging routes share: sign-in and sign-up run
limit()→rules(env)→limit_hitsupsert before Better Auth, andGET /api/admin/limitsalso callsrules(env)and readslimit_hits./api/session,/api/levelsand/api/jobsdon't, and they stayed fast. That's worth checking first. Both hang windows came right after digs (Artifacts imports) at 11:04 and 11:26, so a dig may leave something stuck in the isolate.Next step, suggested: deploy with timing logs around
rules(),hit()andauthFor().handler(), reproduce (dig, then sign in), and readwrangler tail.Blocks the last step of #284 (the cron replay of a queued dig after the tab closes).
QuinnsCode commentedon Oct 10, 2026
Found the cause and fixed it in #337, so it doesn't need Fable after all: one Better Auth instance per isolate shared Kysely's connection mutex across requests, and a cancelled request left the lock held.
codeSplitters: a Better Auth instance per request, so one stuck query…
codeSplitters test: the #333 hang test waits for the first request to…
codeSplitters: GDPR — privacy field report, data export, account dele…
Bun 1.4.3 follow-ups: --check on the last four apps' builds, and head…