{"record":{"id":"a576e83101814ff2","repo":"srbhr/Resume-Matcher","slug":"interview-preparation-can-only-be-generated-for-ta","errorCode":null,"errorMessage":"Interview preparation can only be generated for tailored resumes. Please tailor this resume to a job description first.","messagePattern":"Interview preparation can only be generated for tailored resumes\\. Please tailor this resume to a job description first\\.","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"warning","filePath":"apps/backend/app/routers/resumes.py","lineNumber":1925,"sourceCode":"        content=outreach_content,\n        message=\"Outreach message generated successfully\",\n    )\n\n\n@router.post(\n    \"/{resume_id}/generate-interview-prep\",\n    response_model=GenerateInterviewPrepResponse,\n)\nasync def generate_interview_prep_endpoint(\n    resume_id: str,\n) -> GenerateInterviewPrepResponse:\n    \"\"\"Generate interview preparation on-demand for an existing tailored 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    if not resume.get(\"parent_id\"):\n        raise HTTPException(\n            status_code=400,\n            detail=\"Interview preparation can only be generated for tailored resumes. \"\n            \"Please tailor this resume to a job description first.\",\n        )\n\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    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.\",","sourceCodeStart":1907,"sourceCodeEnd":1943,"githubUrl":"https://github.com/srbhr/Resume-Matcher/blob/116f9cc3b00e1ac91734a6c2679bf41ea64a0edc/apps/backend/app/routers/resumes.py#L1907-L1943","documentation":"400 raised when the resume exists but has no parent_id, meaning it is an original uploaded resume rather than a job-tailored copy. Interview prep is only meaningful for tailored resumes because it derives from the job context captured during tailoring.","triggerScenarios":"POSTing the interview-prep route with the base resume ID (parent_id absent) instead of the tailored resume created from a job description.","commonSituations":"Client selecting the wrong resume in the UI, invoking interview prep before running the tailor step, or legacy records without parent_id linking.","solutions":["Tailor the resume to a job description first, then request interview prep for the tailored copy","Make sure the client passes the tailored resume ID (the one with parent_id set)","Inspect the resume record's parent_id to verify which ID to use"],"exampleFix":"// before\nawait generateInterviewPrep(baseResume.id); // 400\n// after\nconst tailored = await tailorResume(baseResume.id, jobId);\nawait generateInterviewPrep(tailored.id);","handlingStrategy":"validation","validationCode":"const resume = await getResume(resumeId);\nif (!resume?.parentId) {\n  throw new Error('Not a tailored resume; tailor to a job before interview prep');\n}\nawait api.generateInterviewPrep(resumeId);","typeGuard":"function isTailored(r: Resume | null | undefined): r is Resume & { parentId: string } {\n  return !!r && typeof r.parentId === 'string' && r.parentId.length > 0;\n}","tryCatchPattern":"try {\n  await api.generateInterviewPrep(resumeId);\n} catch (e) {\n  if (e.response?.status === 400 && /tailored/i.test(e.response.data?.detail ?? '')) {\n    const t = await api.tailorResume(originalResumeId, jobId);\n    return api.generateInterviewPrep(t.id);\n  }\n  throw e;\n}","preventionTips":["Gate interview-prep UI on parent_id presence","Always run tailoring first in the workflow, then prep","Distinguish base vs tailored resume IDs in client state","Add a regression test for prep-on-base-resume rejection"],"tags":["http-400","business-rule","workflow"],"backgroundTag":"missing-tailored-resume","analyzedSha":"116f9cc3b00e1ac91734a6c2679bf41ea64a0edc","analyzedAt":"2026-08-28T22:51:40.999Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}