45 lines
2.2 KiB
Markdown
45 lines
2.2 KiB
Markdown
---
|
|
# nuzlocke-tracker-tatg
|
|
title: 'Bug: Intermittent 401 errors / failed save-load requiring page reload'
|
|
status: completed
|
|
type: bug
|
|
priority: high
|
|
created_at: 2026-03-21T21:50:48Z
|
|
updated_at: 2026-03-22T09:01:42Z
|
|
---
|
|
|
|
## Problem
|
|
|
|
During gameplay, the app intermittently fails to load or save data. A page reload fixes the issue. Likely caused by expired Supabase JWT tokens not being refreshed automatically before API calls.
|
|
|
|
## Current Implementation
|
|
|
|
- Auth uses Supabase JWTs verified with HS256 (`backend/auth.py:39-44`)
|
|
- Frontend gets token via `supabase.auth.getSession()` in `client.ts:16-21`
|
|
- `getAuthHeaders()` returns the cached session token without checking expiry
|
|
- When the token expires between interactions, API calls return 401
|
|
- Page reload triggers a fresh `getSession()` which refreshes the token
|
|
|
|
## Root Cause Analysis
|
|
|
|
`getSession()` returns the cached token. If it's expired, the frontend sends an expired JWT to the backend, which rejects it with 401. The frontend doesn't call `refreshSession()` or handle token refresh before API calls.
|
|
|
|
## Proposed Fix
|
|
|
|
- [x] Add token refresh logic before API calls (check expiry, call `refreshSession()` if needed)
|
|
- [x] Add 401 response interceptor that automatically refreshes token and retries the request
|
|
- [x] Verify Supabase client `autoRefreshToken` option is enabled
|
|
- [x] Test with short-lived tokens to confirm refresh works (manual verification needed)
|
|
- [x] Check if there's a race condition when multiple API calls trigger refresh simultaneously (supabase-js v2 handles this with internal mutex)
|
|
|
|
## Summary of Changes
|
|
|
|
- **supabase.ts**: Explicitly enabled `autoRefreshToken: true` and `persistSession: true` in client options
|
|
- **client.ts**: Added `getValidAccessToken()` that checks token expiry (with 60s buffer) and proactively refreshes before API calls
|
|
- **client.ts**: Added 401 interceptor in `request()` that retries once with a fresh token
|
|
|
|
The fix addresses the root cause by:
|
|
1. Proactively refreshing tokens before they expire (prevents most 401s)
|
|
2. Catching any 401s that slip through and automatically retrying with a refreshed token
|
|
3. Ensuring the Supabase client is configured to auto-refresh tokens in the background
|