{"record":{"id":"7a24cea10650bf4e","repo":"srbhr/Resume-Matcher","slug":"failed-to-download-resume-status-res-status","errorCode":null,"errorMessage":"Failed to download resume (status ${res.status}): ${text}","messagePattern":"Failed to download resume \\(status (.+?)\\): (.+?)","errorType":"http","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/frontend/lib/api/resume.ts","lineNumber":271,"sourceCode":"    params.set('pageSize', 'A4');\n  }\n  if (locale) {\n    params.set('lang', locale);\n  }\n\n  return `${API_BASE}/resumes/${encodeURIComponent(normalizedId)}/pdf?${params.toString()}`;\n}\n\nexport async function downloadResumePdf(\n  resumeId: string,\n  settings?: TemplateSettings,\n  locale?: Locale\n): Promise<Blob> {\n  const url = getResumePdfUrl(resumeId, settings, locale);\n  const res = await apiFetch(url);\n  if (!res.ok) {\n    const text = await res.text().catch(() => '');\n    throw new Error(`Failed to download resume (status ${res.status}): ${text}`);\n  }\n  return await res.blob();\n}\n\n/** Deletes a resume by ID */\nexport async function deleteResume(resumeId: string): Promise<void> {\n  const res = await apiDelete(`/resumes/${encodeURIComponent(resumeId)}`);\n  if (!res.ok) {\n    const text = await res.text().catch(() => '');\n    throw new Error(`Failed to delete resume (status ${res.status}): ${text}`);\n  }\n}\n\n/** Updates the cover letter for a resume */\nexport async function updateCoverLetter(resumeId: string, content: string): Promise<void> {\n  const res = await apiPatch(`/resumes/${encodeURIComponent(resumeId)}/cover-letter`, { content });\n  if (!res.ok) {\n    const text = await res.text().catch(() => '');","sourceCodeStart":253,"sourceCodeEnd":289,"githubUrl":"https://github.com/srbhr/Resume-Matcher/blob/116f9cc3b00e1ac91734a6c2679bf41ea64a0edc/apps/frontend/lib/api/resume.ts#L253-L289","documentation":"downloadResumePdf fetches a generated PDF blob for a resume via GET on the URL built by getResumePdfUrl (resume id, optional render settings and locale). If the response is not OK it captures the body text and throws this Error with the status and server detail; the caller's blob() then never receives data. It indicates PDF generation/download failed server-side.","triggerScenarios":"apiFetch(getResumePdfUrl(resumeId, settings, locale)) returns non-2xx: PDF render job failure on the backend (500), invalid settings/locale producing a 400, unknown resumeId (404), or auth rejection (401/403). Malformed query params for settings can also trigger a 422.","commonSituations":"Downloading a PDF for a resume whose content contains data the renderer cannot handle (500); passing a locale code the backend does not support; bookmarked/download URL reuse after the resume was deleted; expired session during a long builder session.","solutions":["Inspect status + body text in the message; a 500 usually requires checking backend PDF-render logs for the failing resume content.","Validate the settings/locale values passed to getResumePdfUrl against what the backend supports (400/422).","Confirm the resume still exists before attempting download (404) and refresh the resume list.","Catch the error in the UI, show a download-failed toast, and offer a retry of the PDF fetch."],"exampleFix":"// before\nconst blob = await downloadResumePdf(resumeId, settings, locale);\n\n// after\nlet blob: Blob;\ntry {\n  blob = await downloadResumePdf(resumeId, settings, locale);\n} catch (e) {\n  console.error('PDF download failed:', (e as Error).message);\n  notifyUser('Could not download PDF — please retry.');\n  return;\n}","handlingStrategy":"try-catch","validationCode":"const list = await fetchResumeList(false);\nif (!list.some((r) => r.id === resumeId)) {\n  throw new Error(`Resume ${resumeId} not found; skip PDF download`);\n}","typeGuard":"function isBlob(x: unknown): x is Blob {\n  return typeof Blob !== 'undefined' && x instanceof Blob;\n}","tryCatchPattern":"try {\n  const blob = await downloadResumePdf(resumeId, settings, locale);\n} catch (e) {\n  if ((e as Error).message.includes('status 5')) {\n    notifyUser('PDF generation failed on the server; try again later.');\n  } else {\n    notifyUser('Download failed: ' + (e as Error).message);\n  }\n}","preventionTips":["Only offer PDF download for locales/settings known to be supported by the backend.","Verify the resume exists (list fetch) before building the download URL.","Offer a retry button — transient 500s from the renderer are common.","Keep auth fresh for long builder sessions so the download request is not rejected with 401."],"tags":["http-status","pdf","download","api-client"],"backgroundTag":"http-error-response","analyzedSha":"116f9cc3b00e1ac91734a6c2679bf41ea64a0edc","analyzedAt":"2026-08-28T22:51:40.999Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}