koala73/worldmonitor · error · Error

Authentication unavailable while loading Business Pro seats.

Error message

Authentication unavailable while loading Business Pro seats. Try again.

What it means

Thrown by listBusinessSeats() in src/services/billing.ts when the Convex client and API are available but waitForConvexAuthForUser(userId) returns false while the same Clerk user is still current. That helper waits up to 10 s for the Convex WebSocket auth barrier — the server-confirmed setAuth for this exact userId — and also fails if the barrier was superseded by a newer auth generation. The error means: signed in via Clerk, Convex reachable enough to construct a client, but Convex never confirmed this user's authentication in time, so the businessSeats.listSeats query is not issued.

Source

Thrown at src/services/billing.ts:496

  ownerDomain: string | null;
  ownerIsCorporateDomain: boolean;
  seats: BusinessSeat[];
}

/** List the caller's Business Pro seats. Only the owner sees their own grants. */
export async function listBusinessSeats(): Promise<ListBusinessSeatsResult> {
  const userId = getCurrentClerkUser()?.id;
  if (!userId) {
    return { businessSubscriptionId: null, ownerDomain: null, ownerIsCorporateDomain: false, seats: [] };
  }
  const client = await getConvexClient();
  const api = await getConvexApi();
  if (!client || !api) {
    return { businessSubscriptionId: null, ownerDomain: null, ownerIsCorporateDomain: false, seats: [] };
  }
  if (!await waitForConvexAuthForUser(userId)) {
    assertAccountStillCurrent(userId, 'loading Business Pro seats');
    throw new Error('Authentication unavailable while loading Business Pro seats. Try again.');
  }
  return settleAccountOperation(
    userId,
    'loading Business Pro seats',
    () => client.query(api.payments.businessSeats.listSeats, {}),
  );
}

/** Invite up to 4 same-domain teammates to Business Pro seats. */
export async function inviteBusinessSeats(emails: string[]): Promise<{
  invited: Array<{ email: string; grantId: string; status: 'created' | 'already_pending' | 'already_accepted' }>;
}> {
  const userId = requireSignedInUserId('invite Business Pro seats');
  const client = await getConvexClient();
  const api = await getConvexApi();
  if (!client || !api) throw new Error('Convex unavailable');
  await requireCurrentConvexUser(userId, 'inviting Business Pro seats');
  return settleAccountOperation(

View on GitHub (pinned to eeab0a219f)

Solutions

  1. Retry the load once after a short delay — the barrier usually settles just after the timeout, and the second call typically succeeds.
  2. In DevTools → Network → WS, confirm the wss://…convex.cloud socket connects and authenticates; a failing upgrade points to proxy/VPN interference.
  3. Verify the Clerk keys and VITE_CONVEX_URL belong to the same deployment pairing (Convex auth configured for this Clerk instance).
  4. If it reproduces deterministically for one user, check for auth-generation churn: rapid sign-out/sign-in loops that permanently supersede the waited barrier.

Example fix

// before
const seats = await listBusinessSeats();

// after
let seats;
try {
  seats = await listBusinessSeats();
} catch (err) {
  if (err instanceof Error && err.message.startsWith('Authentication unavailable')) {
    await new Promise((r) => setTimeout(r, 1500));
    seats = await listBusinessSeats();
  } else {
    throw err;
  }
}
Defensive patterns

Strategy: retry

Validate before calling

import { waitForConvexAuthForUser } from '@/services/convex-client';
import { getCurrentClerkUser } from '@/services/clerk';

const userId = getCurrentClerkUser()?.id;
if (!userId) return emptySeats;
if (!await waitForConvexAuthForUser(userId, 15_000)) {
  showAuthPendingUi();
  return;
}
const seats = await listBusinessSeats();

Try / catch

try {
  return await listBusinessSeats();
} catch (err) {
  if (err instanceof Error && err.message.startsWith('Authentication unavailable')) {
    await delay(1500); // barrier usually settles just past the 10s gate
    return await listBusinessSeats();
  }
  throw err;
}

Prevention

When it happens

Trigger: Opening the Business Pro seats UI within the first seconds after sign-in on a slow link (barrier not yet settled at the 10 s timeout); Clerk token fetch stalling so setAuth never completes; the Convex WebSocket being blocked or dropped by a corporate proxy/VPN; rapid sign-out/sign-in creating a newer auth generation that invalidates the waited barrier.

Common situations: Slow mobile networks right after login; locked-down enterprise networks that allow HTTPS but break WebSocket upgrades; Clerk dev-instance rate limits delaying token issuance; environments where VITE_CONVEX_URL points at a deployment that rejects the Clerk token (misconfigured auth provider).

Understand the failure class

Related errors


AI-assisted analysis of koala73/worldmonitor@eeab0a219f (2026-08-21). Data as JSON: /api/errors/f77fc9e069708bbf. Report an issue: GitHub.