Handling Authentication Errors
All features MUST handle AppTokenValidationError responses from the API. When the feature token expires, the API returns a 401 with this body:
{
"name": "AppTokenValidationError",
"message": "Fail to validate app token",
"reason": "expired"
}
Implementation
1. Detect AppTokenValidationError in API calls
The error name may appear at different nesting levels depending on the SDK. Check all of them:
function isAppTokenValidationError(error: unknown): boolean {
if (error && typeof error === 'object') {
const err = error as any
const names = [err.name, err.data?.name, err.error?.name, err.body?.name]
return names.includes('AppTokenValidationError')
}
return false
}
Create a custom AuthTokenExpiredError class. In every API call's catch block, check with the function above and throw AuthTokenExpiredError if matched; otherwise rethrow.
2. Show a "Session Expired" modal
When AuthTokenExpiredError is caught at the UI level, display a centered modal:
- Title: "Session Expired"
- Message: "Your authentication expired, please refresh the page to authenticate again."
- Buttons: "Refresh page" (calls
window.location.reload()) and "Cancel" (closes modal)
Manage modal open/close state in App.tsx and pass an onAuthError callback to child components that make API calls.
Critical: /users/me Exception
The /users/me endpoint MUST NOT trigger AuthTokenExpiredError.
When a feature is public, anonymous visitors receive a 401 from /users/me. This is expected — it means "not authenticated", NOT "session expired". Throwing AuthTokenExpiredError here causes the Session Expired modal to appear immediately for every anonymous visitor.
export async function fetchCurrentUser(
featureToken: string
): Promise<{ id: number; email: string } | null> {
try {
const response = await fetch(
'https://app-api.{FUSEBASE_HOST}/v4/api/users/me',
{ headers: { 'x-app-feature-token': featureToken } }
)
if (!response.ok) return null // Do NOT throw AuthTokenExpiredError
return await response.json()
} catch {
return null
}
}
Rule of thumb
/users/me401 → returnnull(user is anonymous/guest)- Dashboard/data API 401 with
AppTokenValidationError→ throwAuthTokenExpiredError(session expired)