srbhr/Resume-Matcher · error · Error

${data.detail || Failed to generate enhancements (status ${r

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.

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)

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.