diff --git a/app/lib/api-client.ts b/app/lib/api-client.ts index 8bf6727..4a2f656 100644 --- a/app/lib/api-client.ts +++ b/app/lib/api-client.ts @@ -159,10 +159,16 @@ function markdownToText(markdown: string): string { async function getServiceToken(session: OAuthSession, pdsUrl: string): Promise { const apiDid = import.meta.env.VITE_API_DID if (!apiDid) throw new Error('VITE_API_DID is not configured') - const res = await session.fetchHandler( - `${pdsUrl}/xrpc/com.atproto.server.getServiceAuth?aud=${encodeURIComponent(apiDid)}&lxm=com.atproto.server.getServiceAuth`, - { method: 'GET' }, - ) + const url = `${pdsUrl}/xrpc/com.atproto.server.getServiceAuth?aud=${encodeURIComponent(apiDid)}&lxm=com.atproto.server.getServiceAuth` + let res = await session.fetchHandler(url, { method: 'GET' }) + if (res.status === 401) { + // A single 401 is not proof the session is dead: another tab may have + // rotated the tokens, or this request may have raced a refresh. Retry + // once (fetchHandler re-syncs the stored session) and only treat a + // repeat 401 as expiry, since DataProvider signs out on that error. + await sleep(500) + res = await session.fetchHandler(url, { method: 'GET' }) + } if (!res.ok) { if (res.status === 401) throw new SessionExpiredError() const body = await res.text().catch(() => '')