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

  1. Redirect the user to the login flow before invoking authenticated relay APIs.
  2. Check authRuntime.getToken() (or an isAuthenticated flag) before calling, and skip/queue the request if null.
  3. Await auth initialization/hydration so getToken doesn't return null during startup.
  4. 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

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

Related errors


AI-assisted analysis of BloopAI/vibe-kanban@4deb7eca8f (2026-08-29). Data as JSON: /api/errors/52853f10482522f4. Report an issue: GitHub.