BloopAI/vibe-kanban · error
Not authenticated
Error message
Not authenticated
What it means
makeAuthenticatedRequest calls the auth runtime's getToken() before issuing any relay backend request; if no token is available it throws 'Not authenticated' instead of sending an unauthenticated request. Note this fires only when there is no token at all — an expired token yields a 401 and a different error ('Session expired. Please log in again.').
Source
Thrown at packages/web-core/src/shared/lib/relayBackendApi.ts:133
hostId: string,
sessionId: string,
path: string,
options: RequestInit = {}
): Promise<Response> {
const baseUrl = buildRemoteSessionBaseUrl(hostId, sessionId);
return makeAuthenticatedRequest(baseUrl, path, options);
}
async function makeAuthenticatedRequest(
baseUrl: string,
path: string,
options: RequestInit = {},
retryOn401 = true
): Promise<Response> {
const authRuntime = getAuthRuntime();
const token = await authRuntime.getToken();
if (!token) {
throw new Error('Not authenticated');
}
const headers = new Headers(options.headers ?? {});
if (!headers.has('Content-Type')) {
headers.set('Content-Type', 'application/json');
}
headers.set('Authorization', `Bearer ${token}`);
headers.set('X-Client-Version', __APP_VERSION__);
headers.set('X-Client-Type', 'frontend');
const response = await fetch(`${baseUrl}${path}`, {
...options,
headers,
credentials: 'include',
});
if (response.status === 401 && retryOn401) {
const newToken = await authRuntime.triggerRefresh();View on GitHub (pinned to 4deb7eca8f)
Solutions
- Redirect the user to the login flow before invoking authenticated relay APIs.
- Check authRuntime.getToken() (or an isAuthenticated flag) before calling, and skip/queue the request if null.
- Await auth initialization/hydration so getToken doesn't return null during startup.
- After login, retry the request; the runtime's triggerRefresh only helps with expired tokens, not missing ones.
Example fix
// before: calling the API unconditionally
const res = await refreshRelaySigningSession(hostId, sessionId, payload);
// after: guard on token presence
const token = await getAuthRuntime().getToken();
if (!token) {
redirectToLogin();
return;
}
const res = await refreshRelaySigningSession(hostId, sessionId, payload); Defensive patterns
Strategy: try-catch
Validate before calling
const token = await getAuthRuntime().getToken();
if (!token) {
redirectToLogin();
throw new Error('Skipped: no auth token');
} Type guard
function hasToken(t: string | null | undefined): t is string {
return typeof t === 'string' && t.length > 0;
} Try / catch
try {
const res = await makeAuthenticatedRelaySessionRequest(hostId, sessionId, path, opts);
} catch (e) {
if (e instanceof Error && e.message === 'Not authenticated') {
redirectToLogin();
} else throw e;
} Prevention
- Gate authenticated API calls behind an isAuthenticated check or auth-ready promise
- Redirect to login when getToken() returns null instead of proceeding
- Distinguish 'no token' from 'expired token' (401) — only the latter is fixable via triggerRefresh
- Handle multi-tab logout clearing shared auth storage
When it happens
Trigger: Calling any relay backend API (e.g. refreshRelaySigningSession) before the user has logged in; getToken() returning null because the session was never established or was cleared from storage; app loaded directly into a page requiring auth without a login redirect.
Common situations: Deep-linking to a relay session page without an active session; auth storage cleared by logout in another tab; app opened before the auth provider finished initializing and getToken resolves null.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- No peer key found for signing session {}
- OAuth init failed (${res.status})
- Auth methods lookup failed (${res.status})
- OAuth redeem failed (${res.status})
- Local login failed (${res.status})
AI-assisted analysis of BloopAI/vibe-kanban@4deb7eca8f (2026-08-29).
Data as JSON: /api/errors/52853f10482522f4.
Report an issue: GitHub.