koala73/worldmonitor · error · Error
Authentication unavailable while loading MCP clients. Try ag
Error message
Authentication unavailable while loading MCP clients. Try again.
What it means
Thrown by listMcpClients() in src/services/mcp-clients.ts when the Convex client and API loaded fine but waitForConvexAuthForUser(userId) returned false for the still-current Clerk user. That gate waits up to 10 s for the Convex server to confirm setAuth for exactly this userId and fails when the barrier times out or is superseded by a newer auth generation. The listProMcpTokens query is skipped because issuing it unauthenticated would fail server-side Clerk auth.
Source
Thrown at src/services/mcp-clients.ts:52
}
export interface McpQuota {
used: number;
/** Plan-resolved daily allowance. `null` = unlimited (plan 2026-07-25-001 U3b). */
limit: number | null;
resetsAt: string;
}
/** List all Pro MCP tokens for the current user. */
export async function listMcpClients(): Promise<McpClientInfo[]> {
const userId = getCurrentClerkUser()?.id;
if (!userId) return [];
const [client, api] = await Promise.all([getConvexClient(), getConvexApi()]);
if (!client || !api) return [];
if (!await waitForConvexAuthForUser(userId)) {
assertAccountStillCurrent(userId, 'loading MCP clients');
throw new Error('Authentication unavailable while loading MCP clients. Try again.');
}
// Mirror services/api-keys.ts:listApiKeys cast pattern — the generated
// Convex `api` is fully typed at module level but each service casts
// `as any` at the call-site to avoid pulling the entire generated index
// type into every service file.
const rows = await settleAccountOperation(
userId,
'loading MCP clients',
() => client.query((api as any).mcpProTokens.listProMcpTokens, {}),
);
assertAccountStillCurrent(userId, 'loading MCP clients');
return rows as McpClientInfo[];
}
/**
* Revoke a Pro MCP token by tokenId.
*View on GitHub (pinned to eeab0a219f)
Solutions
- Retry the listing after a brief delay — the auth barrier normally settles just past the timeout.
- Confirm in DevTools (Network → WS) that the Convex socket connects and authenticates; investigate proxy/VPN interference if it stalls.
- Check that Clerk and Convex are paired correctly (same deployment, working token exchange) if the error is deterministic.
- Render an empty-but-retryable state in the MCP clients tab for this error instead of a hard failure.
Example fix
// before
const clients = await listMcpClients();
// after
let clients: McpClientInfo[];
try {
clients = await listMcpClients();
} catch (err) {
if (err instanceof Error && err.message.startsWith('Authentication unavailable')) {
await new Promise((r) => setTimeout(r, 1500));
clients = await listMcpClients();
} 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 [];
if (!await waitForConvexAuthForUser(userId, 15_000)) {
renderClientsRetryableEmpty();
return [];
}
return await listMcpClients(); Try / catch
try {
return await listMcpClients();
} catch (err) {
if (err instanceof Error && err.message.startsWith('Authentication unavailable')) {
await delay(1500);
return await listMcpClients();
}
throw err;
} Prevention
- Load the MCP clients tab data after the Convex auth barrier confirms, not concurrently with sign-in.
- Expose a manual refresh on the tab for transient auth settling instead of showing a dead error.
- Track how often the 10 s barrier times out per network to catch proxy/WebSocket interference early.
When it happens
Trigger: Opening the Connected MCP clients settings tab immediately after sign-in before the Convex WebSocket auth handshake completes (10 s barrier timeout); a corporate proxy blocking the Convex WebSocket so setAuth never confirms; Clerk token issuance stalling; sign-out/sign-in churn replacing the auth barrier generation mid-wait.
Common situations: Slow first-load networks; enterprise networks that break WebSocket upgrades; Clerk dev-instance slowness; users who sign out and back in quickly while the settings panel is already mounted.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Authentication unavailable while loading Business Pro seats.
- REDIS_DOWN
- UNAUTHENTICATED
- Revoke service is temporarily unavailable. Try again in a mo
- HTTP ${response.status}
AI-assisted analysis of koala73/worldmonitor@eeab0a219f (2026-08-21).
Data as JSON: /api/errors/03aeed8e238b0e42.
Report an issue: GitHub.