Skip to content

fix: deduplicate 401 logout and fix error interceptor - #561

Merged
scottdraves merged 1 commit into
stagefrom
fix/studio-session-signout
Mar 13, 2026
Merged

fix: deduplicate 401 logout and fix error interceptor#561
scottdraves merged 1 commit into
stagefrom
fix/studio-session-signout

Conversation

@mcarlson

@mcarlson mcarlson commented Mar 13, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Deduplicates concurrent 401 logout handling — multiple simultaneous 401 responses now trigger only one logout() + navigate cycle
  • Fixes bug where non-401 errors (403, 500, etc.) were resolved instead of rejected by the axios response interceptor (return error.responsereturn Promise.reject(error))
  • Reduces studio batch size from 5 to 1 to serialize requests until the backend session refresh dedup fix lands

Root Cause Analysis

The Bug

When the studio page fires multiple concurrent API requests (batch submission sends up to 5 at a time via Promise.allSettled), and the user's WorkOS access token has expired, all concurrent requests race to refresh the same session. WorkOS refresh tokens are single-use (rotated on refresh). Only 1 request wins; the others fail.

Failure Trace

  1. Studio batch submit (useBatchSubmit.ts:84) fires up to 5 concurrent Promise.allSettled requests
  2. All 5 requests arrive at requireAuth middleware with the same expired session cookie
  3. Each calls authenticateWorkOS()authenticateAndGetWorkOSSession() returns null (expired)
  4. Each calls refreshWorkOSSession() — but WorkOS refresh tokens are single-use
  5. Request feat: update on app to test cicd #1 wins the refresh, gets new sealed session, updates cookie in response
  6. Requests feat: adding version to main screen #2-5 fail refresh (token already consumed) → caught by catch block → returns null
  7. null result → handleWorkOSAuthFailure()clears the wos-session cookie and returns 401
  8. Frontend axios interceptor catches each 401 → calls logout() multiple times → navigates to sign-in

Why Only Studio

The studio page is the only feature that fires concurrent authenticated API requests. Normal pages make sequential requests, so the refresh happens once and subsequent requests use the new cookie.

Additional Bug: Error Swallowing

useHttpInterceptors.ts:48 had return error.response which resolved the promise for non-401 errors (like 403 Forbidden). This meant role check failures and other server errors were silently treated as successful responses by calling code, masking related auth issues.

Changes

  • src/hooks/useHttpInterceptors.ts: Added isLoggingOut flag to deduplicate 401 handling; fixed non-401 error path to properly reject
  • src/components/pages/studio/hooks/useBatchSubmit.ts: BATCH_SIZE 5 → 1 (temporary safety measure until backend fix deploys)

Companion PR

Test plan

  • Deploy to stage with backend fix and verify no more sign-outs during studio batch
  • Verify normal 401 (expired session) still redirects to sign-in
  • Verify API errors (403, 500) are now properly surfaced to calling code

🤖 Generated with Claude Code

Multiple concurrent 401 responses no longer each trigger separate
logout+navigate cycles. Non-401 errors now properly reject instead
of resolving with error.response. Batch size reduced to 1 to
serialize studio requests until backend session refresh dedup lands.

Fixes studio page sign-out caused by concurrent request race condition.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying frontend-alpha with  Cloudflare Pages  Cloudflare Pages

Latest commit: 0d70435
Status: ✅  Deploy successful!
Preview URL: https://0c126f10.frontend-btm.pages.dev
Branch Preview URL: https://fix-studio-session-signout.frontend-btm.pages.dev

View logs

@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying frontend-stage with  Cloudflare Pages  Cloudflare Pages

Latest commit: 0d70435
Status: ✅  Deploy successful!
Preview URL: https://bfa98b12.frontend-d7v.pages.dev
Branch Preview URL: https://fix-studio-session-signout.frontend-d7v.pages.dev

View logs

@scottdraves
scottdraves merged commit 700ecd8 into stage Mar 13, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants