{"record":{"id":"436300981fc76c85","repo":"srbhr/Resume-Matcher","slug":"no-cover-letter-found-for-this-resume","errorCode":null,"errorMessage":"No cover letter found for this resume","messagePattern":"No cover letter found for this resume","errorType":"http","errorClass":"HTTPException","httpStatus":404,"severity":"error","filePath":"apps/backend/app/routers/resumes.py","lineNumber":2040,"sourceCode":"async def download_cover_letter_pdf(\n    resume_id: str,\n    pageSize: str = Query(\"A4\", pattern=\"^(A4|LETTER)$\"),\n    lang: str | None = Query(None, pattern=\"^[a-z]{2}(-[A-Z]{2})?$\"),\n) -> Response:\n    \"\"\"Generate a PDF for a cover letter using headless Chromium.\n\n    Args:\n        resume_id: The ID of the resume containing the cover letter\n        pageSize: A4 or LETTER\n        lang: locale used for print page translations\n    \"\"\"\n    resume = await db.get_resume(resume_id)\n    if not resume:\n        raise HTTPException(status_code=404, detail=\"Resume not found\")\n\n    cover_letter = resume.get(\"cover_letter\")\n    if not cover_letter:\n        raise HTTPException(\n            status_code=404, detail=\"No cover letter found for this resume\"\n        )\n\n    # Build print URL (same pattern as resume PDF)\n    url = f\"{settings.frontend_base_url}/print/cover-letter/{resume_id}?pageSize={pageSize}\"\n    if lang:\n        url = f\"{url}&lang={lang}\"\n\n    # Render PDF with cover letter selector\n    try:\n        pdf_bytes = await render_resume_pdf(\n            url, pageSize, selector=\".cover-letter-print\"\n        )\n    except PDFRenderError as e:\n        raise HTTPException(status_code=503, detail=str(e))\n\n    headers = {\n        \"Content-Disposition\": f'attachment; filename=\"cover_letter_{resume_id}.pdf\"'","sourceCodeStart":2022,"sourceCodeEnd":2058,"githubUrl":"https://github.com/srbhr/Resume-Matcher/blob/116f9cc3b00e1ac91734a6c2679bf41ea64a0edc/apps/backend/app/routers/resumes.py#L2022-L2058","documentation":"HTTP 404 raised when the resume exists but has no cover_letter field/content. The PDF renderer needs stored cover-letter content to build the print page; without it there is nothing to render, so the endpoint returns 404 rather than an empty PDF.","triggerScenarios":"Request the cover-letter PDF for a resume whose cover letter was never generated or was cleared — resume.get(\"cover_letter\") is falsy.","commonSituations":"User never generated a cover letter for that resume; a regeneration/edit cleared the field; older resume records predating the cover_letter schema; partial save during generation failure.","solutions":["Generate the cover letter for the resume first, then retry the PDF download.","If a cover letter existed, check generation logs for a failed/aborted save that left the field empty.","Gate the download button in the UI on cover_letter being present."],"exampleFix":"// before\ncover_letter = resume.get(\"cover_letter\")\nif not cover_letter:\n    raise HTTPException(status_code=404, detail=\"No cover letter found for this resume\")\n// after (client-side gate)\nconst canDownload = Boolean(resume.cover_letter);\ndownloadButton.disabled = !canDownload;","handlingStrategy":"validation","validationCode":"const resume = await getResume(id);\nif (!resume) throw new SkipError('resume missing');\nif (!resume.cover_letter) {\n  await generateCoverLetter(id); // create content before downloading PDF\n}","typeGuard":"function hasCoverLetter(r) {\n  return r != null && typeof r.cover_letter === 'string' && r.cover_letter.trim().length > 0;\n}","tryCatchPattern":"try {\n  return await downloadCoverLetterPdf(resumeId);\n} catch (e) {\n  if (e.status === 404 && /cover letter/i.test(e.detail)) {\n    await generateCoverLetter(resumeId);\n    return downloadCoverLetterPdf(resumeId); // retry once after generating\n  }\n  throw e;\n}","preventionTips":["Gate the PDF download button on cover_letter being present in the resume object.","Verify cover-letter generation persisted successfully before marking it complete in the UI.","Backfill cover_letter for legacy resumes if the feature was added later."],"tags":["http-404","missing-data","cover-letter","pdf"],"backgroundTag":"missing-resource-content","analyzedSha":"116f9cc3b00e1ac91734a6c2679bf41ea64a0edc","analyzedAt":"2026-08-28T22:51:40.999Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}