{"record":{"id":"5cc343c2983a88d0","repo":"srbhr/Resume-Matcher","slug":"data-detail-failed-to-generate-enhancements","errorCode":null,"errorMessage":"${data.detail || Failed to generate enhancements (status ${res.status}).}","messagePattern":"\\$\\{data\\.detail \\|\\| Failed to generate enhancements \\(status \\$\\{res\\.status\\}\\)\\.\\}","errorType":"http","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/frontend/lib/api/enrichment.ts","lineNumber":80,"sourceCode":"\n  return res.json();\n}\n\n/**\n * Generate enhanced descriptions from user answers.\n */\nexport async function generateEnhancements(\n  resumeId: string,\n  answers: AnswerInput[]\n): Promise<EnhancementPreview> {\n  const res = await apiPost('/enrichment/enhance', {\n    resume_id: resumeId,\n    answers,\n  });\n\n  if (!res.ok) {\n    const data = await res.json().catch(() => ({}));\n    throw new Error(data.detail || `Failed to generate enhancements (status ${res.status}).`);\n  }\n\n  return res.json();\n}\n\n/**\n * Apply enhancements to the master resume.\n */\nexport async function applyEnhancements(\n  resumeId: string,\n  enhancements: EnhancedDescription[]\n): Promise<{ message: string; updated_items: number }> {\n  const res = await apiPost(`/enrichment/apply/${resumeId}`, {\n    enhancements,\n  });\n\n  if (!res.ok) {\n    const data = await res.json().catch(() => ({}));","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/srbhr/Resume-Matcher/blob/116f9cc3b00e1ac91734a6c2679bf41ea64a0edc/apps/frontend/lib/api/enrichment.ts#L62-L98","documentation":"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.","triggerScenarios":"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.","commonSituations":"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).","solutions":["Read res.status and the JSON detail to pinpoint 401 vs 404 vs 422 vs 5xx.","For 422: validate the answers payload matches the API schema (each answer has question id and non-empty text) before calling.","For 401: redirect the user to re-login or refresh the session before retrying.","For 429/5xx: retry with exponential backoff, and check backend AI provider config/quota.","For 404: verify the resumeId exists; re-select the resume if it was deleted."],"exampleFix":"// before\nconst res = await apiPost('/enrichment/generate', { resume_id: resumeId, answers });\nif (!res.ok) {\n  const data = await res.json().catch(() => ({}));\n  throw new Error(data.detail || `Failed to generate enhancements (status ${res.status}).`);\n}\n// after\nconst res = await apiPost('/enrichment/generate', { resume_id: resumeId, answers });\nif (!res.ok && res.status === 422) {\n  throw new Error('Some answers were invalid. Please review and resubmit.');\n}\nif (!res.ok) {\n  const data = await res.json().catch(() => ({}));\n  throw new Error(data.detail || `Failed to generate enhancements (status ${res.status}).`);\n}","handlingStrategy":"validation","validationCode":"const valid = resumeId?.trim() && Array.isArray(answers) && answers.length > 0 && answers.every(a => a && a.question_id && typeof a.answer === 'string');\nif (!valid) throw new Error('Invalid answers payload for enhancement generation.');","typeGuard":"function hasValidAnswers(a: unknown): a is AnswerInput[] {\n  return Array.isArray(a) && a.length > 0 && a.every(x =>\n    typeof x === 'object' && x !== null && 'question_id' in x && 'answer' in x);\n}","tryCatchPattern":"try {\n  const enhancements = await generateEnhancements(resumeId, answers);\n} catch (e) {\n  const msg = e instanceof Error ? e.message : String(e);\n  if (msg.includes('status 401')) redirectToLogin();\n  else if (msg.includes('status 422')) showToast('Please review your answers and try again.');\n  else showToast('Could not generate enhancements. Please retry in a moment.');\n}","preventionTips":["Validate the answers array against the AnswerInput shape before every call.","Keep the frontend payload type in sync with the backend Pydantic schema; regenerate types on API changes.","Add a retry path with backoff for transient 429/5xx statuses."],"tags":["http-error","fetch","api-client","validation"],"backgroundTag":"http-non-ok-response","analyzedSha":"116f9cc3b00e1ac91734a6c2679bf41ea64a0edc","analyzedAt":"2026-08-28T22:51:40.999Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}