{"record":{"id":"50a17b0653e562ad","repo":"srbhr/Resume-Matcher","slug":"no-job-context-found-for-this-resume-the-resume-m","errorCode":null,"errorMessage":"No job context found for this resume. The resume may have been created before job tracking was implemented.","messagePattern":"No job context found for this resume\\. The resume may have been created before job tracking was implemented\\.","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"error","filePath":"apps/backend/app/routers/resumes.py","lineNumber":1795,"sourceCode":"    - The resume must have an associated job context in the improvements table\n    \"\"\"\n    # Get the resume\n    resume = await db.get_resume(resume_id)\n    if not resume:\n        raise HTTPException(status_code=404, detail=\"Resume not found\")\n\n    # Check if it's a tailored resume (has parent_id)\n    if not resume.get(\"parent_id\"):\n        raise HTTPException(\n            status_code=400,\n            detail=\"Cover letter can only be generated for tailored resumes. \"\n            \"Please tailor this resume to a job description first.\",\n        )\n\n    # Get improvement record to find the job_id\n    improvement = await db.get_improvement_by_tailored_resume(resume_id)\n    if not improvement:\n        raise HTTPException(\n            status_code=400,\n            detail=\"No job context found for this resume. \"\n            \"The resume may have been created before job tracking was implemented.\",\n        )\n\n    # Get the job description\n    job = await db.get_job(improvement[\"job_id\"])\n    if not job:\n        raise HTTPException(\n            status_code=404,\n            detail=\"The associated job description was not found.\",\n        )\n\n    # Get resume data\n    resume_data = resume.get(\"processed_data\")\n    if not resume_data:\n        raise HTTPException(\n            status_code=400,","sourceCodeStart":1777,"sourceCodeEnd":1813,"githubUrl":"https://github.com/srbhr/Resume-Matcher/blob/116f9cc3b00e1ac91734a6c2679bf41ea64a0edc/apps/backend/app/routers/resumes.py#L1777-L1813","documentation":"HTTP 400 raised by generate_cover_letter_endpoint when the resume is tailored (has parent_id) but no improvement record exists in the improvements table linking that tailored resume to a job (db.get_improvement_by_tailored_resume returns None). Without that link the endpoint cannot determine which job description to base the letter on.","triggerScenarios":"Cover-letter generation requested for a tailored resume that has no corresponding row in the improvements table — typically records created before job tracking was implemented, an interrupted tailoring run, or an improvement row deleted manually.","commonSituations":"Legacy data migrated from a pre-job-tracking schema; tailoring job crashed after creating the child resume but before writing the improvement record; DB cleanup scripts removed improvement rows but kept resumes.","solutions":["Re-tailor the resume against the target job so a fresh improvement record linking resume to job_id is created.","If the job is known, insert/backfill the missing improvement record (resume_id + job_id) via a data-fix script.","Audit legacy tailored resumes lacking improvement rows and re-run tailoring for them.","Make the tailor flow transactional so the resume and improvement record are written together."],"exampleFix":"// before\nawait api.post(`/resumes/${resumeId}/generate-cover-letter`); // 400 if no improvement\n\n// after: ensure linkage exists by re-tailoring\nconst resume = await api.get(`/resumes/${resumeId}`);\nif (!resume.data.parent_id || !(await hasImprovement(resumeId))) {\n  const re = await api.post(`/resumes/${resumeId}/retailor`, { jobId });\n  resumeId = re.data.id;\n}\nawait api.post(`/resumes/${resumeId}/generate-cover-letter`);","handlingStrategy":"validation","validationCode":"const resume = await api.get(`/resumes/${resumeId}`);\nif (!resume.data.parent_id) throw new Error('Not a tailored resume');\n// ensure the job linkage (improvement) exists\nconst improvements = await api.get(`/improvements?tailoredResumeId=${resumeId}`);\nif (!improvements.data.length) throw new Error('No job context; re-tailor the resume.');","typeGuard":"const hasJobContext = (r, improvements) => Boolean(r?.parent_id) && improvements.some((i) => i.tailored_resume_id === r.id && i.job_id);","tryCatchPattern":"try {\n  await api.post(`/resumes/${resumeId}/generate-cover-letter`);\n} catch (e) {\n  if (e.response?.status === 400 && /job context/.test(e.response.data?.detail ?? '')) {\n    notify('Job context missing — re-tailoring the resume.');\n    await api.post(`/resumes/${resumeId}/retailor`, { jobId });\n  } else throw e;\n}","preventionTips":["Run a data audit for tailored resumes lacking improvement rows and re-tailor them.","Make tailoring write the resume and improvement record atomically.","Verify job_id linkage after any DB migration affecting improvements."],"tags":["http-400","missing-data","data-integrity"],"backgroundTag":"missing-job-context","analyzedSha":"116f9cc3b00e1ac91734a6c2679bf41ea64a0edc","analyzedAt":"2026-08-28T22:51:40.999Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}