From 4f232957c4acd3ca8ba28638d746556e32acac80 Mon Sep 17 00:00:00 2001 From: kolaente Date: Fri, 3 Apr 2026 20:18:11 +0200 Subject: [PATCH] fix(auth): add retry and logging for token refresh failures Add a single retry with a 1-second delay in the 401 interceptor's doRefresh() before giving up on token renewal. This handles transient failures like brief network blips or server restarts without immediately logging the user out. Also log refresh failures via console.warn so the reason is visible in browser DevTools for easier diagnosis. Ref: #2391 --- frontend/src/helpers/fetcher.ts | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/frontend/src/helpers/fetcher.ts b/frontend/src/helpers/fetcher.ts index 66c89a64a..e243dc0ce 100644 --- a/frontend/src/helpers/fetcher.ts +++ b/frontend/src/helpers/fetcher.ts @@ -38,11 +38,20 @@ async function doRefresh(): Promise { try { await refreshToken(true) return getToken() - } catch { - // Refresh failed. Don't remove the token here — in a multi-tab scenario, - // another tab may have successfully rotated the refresh token, and clearing - // localStorage would log out that tab too. Let the caller decide. - return null + } catch (_e) { + // Single retry after a short delay for transient failures (network + // blip, server restart). If this also fails, give up. + try { + await new Promise(resolve => setTimeout(resolve, 1000)) + await refreshToken(true) + return getToken() + } catch (retryErr) { + // Refresh failed. Don't remove the token here — in a multi-tab scenario, + // another tab may have successfully rotated the refresh token, and clearing + // localStorage would log out that tab too. Let the caller decide. + console.warn('[Vikunja] Token refresh failed:', retryErr) + return null + } } }