fix(login): recover Turnstile widget from transient errors - #3306
fix(login): recover Turnstile widget from transient errors#3306posthog-eu[bot] wants to merge 1 commit into
Conversation
The login captcha marked the widget permanently unavailable on the first Turnstile error and never reset it. Error 300010 and the rest of the 3xxxxx/6xxxxx families are transient (network, WebView, ad-blocker), so a single hiccup stranded the user on a dead captcha and logged an error each time. - Reset and retry the widget a bounded number of times on a recoverable error; give up (and log at error level) only after the budget is spent. - Handle the expired-token callback: Cloudflare does not reset the widget on expiry, so clear the stale token and reset for a fresh challenge. - Show the existing "Captcha not available" message when the widget is unavailable so a blocked user sees why. - Add unit tests for error recoverability and the retry budget. Generated-By: PostHog Desktop Task-Id: 59e9c12b-6ee3-4205-80fe-17c5ff529793
|
Important Review skippedBot user detected. To trigger a single review, invoke the ⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Advanced Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Merging this PR will not alter performance
Comparing Footnotes
|
|



Summary
Recurring login failures traced to
Turnstile error 300010on the captcha-protected login page. Users get stranded on a dead captcha and cannot sign in.src/pages/login.vuemarked the Turnstile widget permanentlyunavailableon the first@errorand never reset it. Error 300010 and the rest of the3xxxxx/6xxxxxfamilies are transient (network, WebView, ad-blocker) and clear after a widget reset — but the page had no recovery path, and each hit logged an error-level line.Changes:
@expiredignored; stale token stayed bound (Cloudflare does not reset on expiry)captcha-not-availablemessageNon-recoverable codes (bad sitekey
110xxx, unsupported browser) still fail fast — retrying would not help.Retry and recoverability logic lives in
src/utils/turnstile.tsas pure functions, so it is unit-tested directly.Note
The
sso_error=enforcement_check_failedredirect seen in the same login URLs comes from a separate router guard (src/modules/sso-enforcement.ts) that fails closed on an unreachable enforcement check. That mechanism works as designed and is out of scope here; this PR targets the high-volume Turnstile captcha lifecycle.Test plan
bun test:unit— new cases intests/turnstile.unit.test.tscover error recoverability (300010/600010recoverable;110200/100000not) and the retry budget (retry while under budget, give up once spent).@errorwith a3xxxxxcode and confirm the widget resets and a token is obtained instead of the form locking up; force a non-recoverable code and confirm the "Captcha not available" message appears.Agent context
vue-turnstileerror-callbackonly re-emits the code and returnsundefined, so the widget does not self-recover — an explicitreset()is required. Itsexpired-callbacklikewise does not reset the widget.Screenshots
Not included — the change adds a captcha-error recovery path and a text message; no new visual layout.
Checklist
bun run lint:backend && bun run lint. (Followed the project style;lint not run in this environment — dependencies could not be installed.)
accordingly.
tests/turnstile.unit.test.ts; no E2E added.)conditions; verified via unit tests and the repro steps above.
Created with PostHog Desktop from this inbox report.
Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.