srbhr/Resume-Matcher · error · Error

).}

Error message

${data.detail || Failed to generate enhancements (status ${res.status}).}

What it means

generateEnhancements in apps/frontend/lib/api/enrichment.ts throws this Error when POSTing the user's answers to the enhancement-generation endpoint returns a non-OK response. Like its siblings, it prefers the server's JSON `detail` field and falls back to a status-embedded generic message. It signals the backend rejected or failed the enhancement generation step.

Solutions

  1. Read res.status and the JSON detail to pinpoint 401 vs 404 vs 422 vs 5xx.
  2. For 422: validate the answers payload matches the API schema (each answer has question id and non-empty text) before calling.
  3. For 401: redirect the user to re-login or refresh the session before retrying.
  4. For 429/5xx: retry with exponential backoff, and check backend AI provider config/quota.
  5. For 404: verify the resumeId exists; re-select the resume if it was deleted.

Example fix

// before
const res = await apiPost('/enrichment/generate', { resume_id: resumeId, answers });
if (!res.ok) {
  const data = await res.json().catch(() => ({}));
  throw new Error(data.detail || `Failed to generate enhancements (status ${res.status}).`);
}
// after
const res = await apiPost('/enrichment/generate', { resume_id: resumeId, answers });
if (!res.ok && res.status === 422) {
  throw new Error('Some answers were invalid. Please review and resubmit.');
}
if (!res.ok) {
  const data = await res.json().catch(() => ({}));
  throw new Error(data.detail || `Failed to generate enhancements (status ${res.status}).`);
}
Defensive patterns

Strategy: validation

Validate before calling

const valid = resumeId?.trim() && Array.isArray(answers) && answers.length > 0 && answers.every(a => a && a.question_id && typeof a.answer === 'string');
if (!valid) throw new Error('Invalid answers payload for enhancement generation.');

Type guard

function hasValidAnswers(a: unknown): a is AnswerInput[] {
  return Array.isArray(a) && a.length > 0 && a.every(x =>
    typeof x === 'object' && x !== null && 'question_id' in x && 'answer' in x);
}

Try / catch

try {
  const enhancements = await generateEnhancements(resumeId, answers);
} catch (e) {
  const msg = e instanceof Error ? e.message : String(e);
  if (msg.includes('status 401')) redirectToLogin();
  else if (msg.includes('status 422')) showToast('Please review your answers and try again.');
  else showToast('Could not generate enhancements. Please retry in a moment.');
}

Prevention

When it happens

Trigger: apiPost(`/enrichment/generate`, { resume_id: resumeId, answers }) resolves with a 4xx/5xx status: 401 unauthenticated, 404 unknown resume_id, 422 answers payload fails server-side validation (missing/malformed answers array), 429 AI rate limit, 500 when the LLM enhancement service errors.

Common situations: User submits wizard answers after their session cookie expired (401); the payload shape drifted from the backend Pydantic schema after an API change (422); the LLM provider times out or quota is exhausted (500/429); resumeId refers to a resume deleted earlier (404).

Related errors


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

Appendix: source

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

  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) {
    const data = await res.json().catch(() => ({}));
    throw new Error(data.detail || `Failed to generate enhancements (status ${res.status}).`);
  }

  return res.json();
}

/**
 * Apply enhancements to the master resume.
 */
export async function applyEnhancements(
  resumeId: string,
  enhancements: EnhancedDescription[]
): Promise<{ message: string; updated_items: number }> {
  const res = await apiPost(`/enrichment/apply/${resumeId}`, {
    enhancements,
  });

  if (!res.ok) {
    const data = await res.json().catch(() => ({}));

View on GitHub (pinned to 116f9cc3b0)