srbhr/Resume-Matcher · warning · HTTPException
Interview preparation can only be generated for tailored res
Error message
Interview preparation can only be generated for tailored resumes. Please tailor this resume to a job description first.
What it means
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.
Source
Thrown at apps/backend/app/routers/resumes.py:1925
content=outreach_content,
message="Outreach message generated successfully",
)
@router.post(
"/{resume_id}/generate-interview-prep",
response_model=GenerateInterviewPrepResponse,
)
async def generate_interview_prep_endpoint(
resume_id: str,
) -> GenerateInterviewPrepResponse:
"""Generate interview preparation on-demand for an existing tailored resume."""
resume = await db.get_resume(resume_id)
if not resume:
raise HTTPException(status_code=404, detail="Resume not found")
if not resume.get("parent_id"):
raise HTTPException(
status_code=400,
detail="Interview preparation can only be generated for tailored resumes. "
"Please tailor this resume to a job description first.",
)
improvement = await db.get_improvement_by_tailored_resume(resume_id)
if not improvement:
raise HTTPException(
status_code=400,
detail="No job context found for this resume. "
"The resume may have been created before job tracking was implemented.",
)
job = await db.get_job(improvement["job_id"])
if not job:
raise HTTPException(
status_code=404,
detail="The associated job description was not found.",View on GitHub (pinned to 116f9cc3b0)
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
Example fix
// before await generateInterviewPrep(baseResume.id); // 400 // after const tailored = await tailorResume(baseResume.id, jobId); await generateInterviewPrep(tailored.id);
Defensive patterns
Strategy: validation
Validate before calling
const resume = await getResume(resumeId);
if (!resume?.parentId) {
throw new Error('Not a tailored resume; tailor to a job before interview prep');
}
await api.generateInterviewPrep(resumeId); Type guard
function isTailored(r: Resume | null | undefined): r is Resume & { parentId: string } {
return !!r && typeof r.parentId === 'string' && r.parentId.length > 0;
} Try / catch
try {
await api.generateInterviewPrep(resumeId);
} catch (e) {
if (e.response?.status === 400 && /tailored/i.test(e.response.data?.detail ?? '')) {
const t = await api.tailorResume(originalResumeId, jobId);
return api.generateInterviewPrep(t.id);
}
throw e;
} Prevention
- 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
When it happens
Trigger: POSTing the interview-prep route with the base resume ID (parent_id absent) instead of the tailored resume created from a job description.
Common situations: Client selecting the wrong resume in the UI, invoking interview prep before running the tailor step, or legacy records without parent_id linking.
Related errors
- Outreach message can only be generated for tailored resumes.
- Cover letter can only be generated for tailored resumes. Ple
- Job description is only available for tailored resumes.
- Unsupported UI language: {request.ui_language}. Supported: {
- Unsupported content language: {request.content_language}. Su
AI-assisted analysis of srbhr/Resume-Matcher@116f9cc3b0 (2026-08-28).
Data as JSON: /api/errors/a576e83101814ff2.
Report an issue: GitHub.