srbhr/Resume-Matcher · error · Error

${data.detail || Failed to analyze resume (status ${res.stat

Error message

${data.detail || Failed to analyze resume (status ${res.status}).}

What it means

analyzeResume in apps/frontend/lib/api/enrichment.ts throws this Error when the POST to the backend resume-analysis endpoint returns a non-OK HTTP response. It first tries to read the JSON body and surface the server-provided `detail` message (FastAPI-style error payloads); if the body is not valid JSON, it falls back to a generic message embedding the HTTP status code. This is a client-side wrapper around any 4xx/5xx backend response during AI resume analysis.

Source

Thrown at apps/frontend/lib/api/enrichment.ts:60

}

export interface EnhancementPreview {
  enhancements: EnhancedDescription[];
}

/**
 * Analyze a resume to identify items that need enrichment.
 * Returns items with weak descriptions and clarifying questions.
 */
export async function analyzeResume(resumeId: string): Promise<AnalysisResponse> {
  const res = await apiFetch(`/enrichment/analyze/${resumeId}`, {
    method: 'POST',
    credentials: 'include',
  });

  if (!res.ok) {
    const data = await res.json().catch(() => ({}));
    throw new Error(data.detail || `Failed to analyze resume (status ${res.status}).`);
  }

  return res.json();
}

/**
 * Generate enhanced descriptions from user answers.
 */
export async function generateEnhancements(
  resumeId: string,
  answers: AnswerInput[]
): Promise<EnhancementPreview> {
  const res = await apiPost('/enrichment/enhance', {
    resume_id: resumeId,
    answers,
  });

  if (!res.ok) {

View on GitHub (pinned to 116f9cc3b0)

Solutions

  1. Log or inspect res.status and the response body to identify whether it is 401/404/429/5xx before changing code.
  2. If 401: re-authenticate the user / refresh the session cookie before calling analyzeResume (credentials: 'include' only sends cookies that exist).
  3. If 404: verify the resumeId is valid and still exists (fetch the resume list first); do not analyze a deleted resume.
  4. If 5xx: check backend logs for the analysis/AI-provider failure (API keys, quota, timeout) and add a retry with backoff for transient 502/503/429.
  5. Confirm NEXT_PUBLIC_API_BASE_URL / proxy config points at the running backend so the route resolves.

Example fix

// before
const res = await fetch(`${API_URL}/enrichment/analyze/${resumeId}`, { method: 'POST', credentials: 'include' });
if (!res.ok) {
  const data = await res.json().catch(() => ({}));
  throw new Error(data.detail || `Failed to analyze resume (status ${res.status}).`);
}
// after
const res = await fetch(`${API_URL}/enrichment/analyze/${resumeId}`, { method: 'POST', credentials: 'include' });
if (res.status === 401) throw new Error('Your session expired. Please sign in again.');
if (!res.ok) {
  const data = await res.json().catch(() => ({}));
  throw new Error(data.detail || `Failed to analyze resume (status ${res.status}).`);
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (!resumeId || !resumeId.trim()) throw new Error('A valid resumeId is required before analyzing.');

Type guard

function isAnalysisError(e: unknown): e is Error & { status?: number } {
  return e instanceof Error && e.message.includes('Failed to analyze resume');
}

Try / catch

try {
  const analysis = await analyzeResume(resumeId);
} catch (e) {
  if (isAnalysisError(e) && /status 401/.test(e.message)) {
    redirectToLogin();
  } else {
    showToast(e instanceof Error ? e.message : 'Analysis failed. Please try again.');
  }
}

Prevention

When it happens

Trigger: The `fetch` POST (with credentials: 'include') resolves with res.ok === false: e.g. 401 when the auth cookie is missing/expired, 404 when resumeId does not exist server-side, 422 when the resumeId format is invalid, 429 rate limiting on the AI analysis backend, or 500/502/503 when the AI analysis service fails or times out.

Common situations: User session expired so cookies are no longer valid (401); the resume was deleted in another tab so the ID is stale (404); the backend LLM provider key is missing/out of quota causing 500; the frontend is pointed at the wrong API base URL so the route 404s; a proxy/gateway returns an HTML error page so res.json() fails and the fallback message appears.

Related errors


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