BloopAI/vibe-kanban · error

Not authenticated

Error message

Not authenticated

What it means

makeAuthenticatedRequest in remoteApi.ts throws 'Not authenticated' when authRuntime.getToken() resolves to null/undefined — there is no access token available at all, so no request is attempted. Unlike the 401 path, this fires before any network call.

Source

Thrown at packages/web-core/src/shared/lib/remoteApi.ts:64

export const makeRequest = async (
  path: string,
  options: RequestInit = {},
  retryOn401 = true
): Promise<Response> => {
  return makeAuthenticatedRequest(getRemoteApiUrl(), path, options, retryOn401);
};

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',
  });

  // Handle 401 - token may have expired
  if (response.status === 401 && retryOn401) {

View on GitHub (pinned to 4deb7eca8f)

Solutions

  1. Gate authenticated API calls behind an isAuthenticated check from the auth runtime.
  2. Await auth initialization (token hydration) before firing requests on app startup.
  3. Redirect to login when no token is present instead of issuing the call.
  4. In tests/scripts, initialize the auth runtime (or mock getAuthRuntime) before calling makeRequest.

Example fix

// before
const projects = await listProjects(); // throws if token missing
// after
const auth = getAuthRuntime();
if (!(await auth.getToken())) {
  redirectToLogin();
  return;
}
const projects = await listProjects();
Defensive patterns

Strategy: try-catch

Validate before calling

const authRuntime = getAuthRuntime();
const token = await authRuntime.getToken();
if (!token) {
  redirectToLogin();
  return; // don't call the API
}

Type guard

function isNotAuthenticatedError(e: unknown): e is Error {
  return e instanceof Error && e.message === 'Not authenticated';
}

Try / catch

try {
  const resp = await makeRequest('/v1/projects');
} catch (e) {
  if (isNotAuthenticatedError(e)) {
    await authRuntime.logout();
    window.location.assign('/login');
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling any remoteApi.makeRequest-wrapped function (projects, issues, attachments, relay hosts) while the user has never logged in, has logged out, or the token store hasn't been hydrated yet (e.g. call fired during app bootstrap before auth initialization completes).

Common situations: Making API calls before AuthProvider/ConfigProvider finish initializing; expired refresh token cleared from storage so getToken() returns null; direct calls in tests or scripts without setting up the auth runtime; deep-link into an authenticated page without a session.

Understand the failure class

Related errors


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