Skip to content

codeSplitters live: email sign-in (and sometimes sign-up, admin limits) hangs on the Worker #333

Closed

Description

@QuinnsCode

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.

🤖 Generated with Claude Code

Activity

  1. added
    fableHand to a Fable agent: needs deeper digging
    on Oct 10, 2026
  2. QuinnsCode commented on Oct 10, 2026

    @QuinnsCode
    OwnerAuthor

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

  3. QuinnsCode commented on Oct 10, 2026

    @QuinnsCode
    OwnerAuthor

    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.

  4. removed
    fableHand to a Fable agent: needs deeper digging
    on Oct 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions