srbhr/Resume-Matcher · error · Error

Failed to fetch system status (status ${res.status}).

Error message

Failed to fetch system status (status ${res.status}).

What it means

fetchSystemStatus calls GET /status with credentials and throws this Error when the response is not ok. It is a thin wrapper — the response body with the actual failure reason is discarded.

Source

Thrown at apps/frontend/lib/api/config.ts:145

    options.headers = { 'Content-Type': 'application/json' };
    options.body = JSON.stringify(config);
  }

  const res = await apiFetch('/config/llm-test', options);

  if (!res.ok) {
    throw new Error(`Failed to test LLM connection (status ${res.status}).`);
  }

  return res.json();
}

// Fetch system status
export async function fetchSystemStatus(): Promise<SystemStatus> {
  const res = await apiFetch('/status', { credentials: 'include' });

  if (!res.ok) {
    throw new Error(`Failed to fetch system status (status ${res.status}).`);
  }

  return res.json();
}

// Provider display names and default models
export const PROVIDER_INFO: Record<
  LLMProvider,
  {
    name: string;
    defaultModel: string;
    requiresKey: boolean;
    requiresBaseUrl?: boolean;
    /**
     * Base URL this provider owns. Used both to seed the field on switch-in
     * and to decide whether to clear it on switch-out, so a previous
     * provider's endpoint can't be persisted against the next one.
     */

View on GitHub (pinned to 116f9cc3b0)

Solutions

  1. Check the status code: 5xx/503 -> inspect backend health and restart it if needed; 404 -> fix the API base URL; 401 -> re-login
  2. Curl the backend /status endpoint directly to isolate frontend vs backend
  3. Ensure frontend and backend versions match (route exists)
  4. For status polling UIs, treat this as non-fatal and retry with backoff

Example fix

// before
const status = await fetchSystemStatus();
// after
const status = await fetchSystemStatus().catch((e) => {
  console.warn('status unavailable:', e.message);
  return { online: false } as SystemStatus;
});
Defensive patterns

Strategy: fallback

Validate before calling

const API_BASE = process.env.NEXT_PUBLIC_API_BASE_URL;
if (!API_BASE) console.warn('NEXT_PUBLIC_API_BASE_URL unset; /status calls may 404');

Type guard

function isStatusError(e: unknown): e is Error & { status?: number } {
  const m = e instanceof Error ? e.message.match(/status (\d{3})/) : null;
  if (e instanceof Error && m) (e as any).status = Number(m[1]);
  return e instanceof Error;
}

Try / catch

let status: SystemStatus;
try {
  status = await fetchSystemStatus();
} catch {
  status = { online: false } as SystemStatus; // render offline badge
}

Prevention

When it happens

Trigger: GET /status returns non-OK: backend down (network error handled separately), 401/403 auth required, 404 wrong API base path, 503 during backend restart or migration.

Common situations: Dashboard/status widget polling while the backend container is restarting; frontend pointed at the wrong port or a stale reverse-proxy route; session cookie expired causing 401.

Understand the failure class

Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.

Related errors


AI-assisted analysis of srbhr/Resume-Matcher@116f9cc3b0 (2026-08-28). Data as JSON: /api/errors/c8b168ba4b17c1eb. Report an issue: GitHub.