srbhr/Resume-Matcher · warning · HTTPException
Cover letter can only be generated for tailored resumes. Ple
Error message
Cover letter can only be generated for tailored resumes. Please tailor this resume to a job description first.
What it means
HTTP 400 raised by generate_cover_letter_endpoint when the resume exists but has no parent_id, meaning it is an original (untailored) resume. Cover letters are generated only from tailored resumes, since the tailored resume carries the job-specific context needed for the letter.
Source
Thrown at apps/backend/app/routers/resumes.py:1786
@router.post(
"/{resume_id}/generate-cover-letter", response_model=GenerateContentResponse
)
async def generate_cover_letter_endpoint(resume_id: str) -> GenerateContentResponse:
"""Generate a cover letter on-demand for an existing tailored resume.
This endpoint allows users to generate a cover letter after a resume has been
tailored, without needing to re-tailor the entire resume. It requires:
- The resume must be a tailored resume (has parent_id)
- The resume must have an associated job context in the improvements table
"""
# Get the resume
resume = await db.get_resume(resume_id)
if not resume:
raise HTTPException(status_code=404, detail="Resume not found")
# Check if it's a tailored resume (has parent_id)
if not resume.get("parent_id"):
raise HTTPException(
status_code=400,
detail="Cover letter can only be generated for tailored resumes. "
"Please tailor this resume to a job description first.",
)
# Get improvement record to find the job_id
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.",
)
# Get the job description
job = await db.get_job(improvement["job_id"])
if not job:
raise HTTPException(View on GitHub (pinned to 116f9cc3b0)
Solutions
- First tailor the resume to a job description (run the tailor flow) to create a child resume with parent_id, then generate the cover letter from that tailored resume.
- Check resume.parent_id client-side and only enable cover-letter generation for tailored resumes.
- Label base vs tailored resumes distinctly in the UI to prevent misclicks.
- If a legacy resume should be tailored, re-run tailoring to create the linked child record.
Example fix
// before
await api.post(`/resumes/${resumeId}/generate-cover-letter`);
// after
const resume = await api.get(`/resumes/${resumeId}`);
if (!resume.data.parent_id) {
const tailored = await api.post(`/resumes/${resumeId}/tailor`, { jobId });
resumeId = tailored.data.id;
}
await api.post(`/resumes/${resumeId}/generate-cover-letter`); Defensive patterns
Strategy: validation
Validate before calling
const resume = await api.get(`/resumes/${resumeId}`);
if (!resume.data.parent_id) {
throw new Error('Not a tailored resume — run the tailor flow first.');
} Type guard
const isTailored = (r) => Boolean(r && r.parent_id);
Try / catch
try {
await api.post(`/resumes/${resumeId}/generate-cover-letter`);
} catch (e) {
if (e.response?.status === 400 && /tailored resumes/.test(e.response.data?.detail ?? '')) {
notify('Please tailor this resume to a job first.');
openTailorDialog(resumeId);
} else throw e;
} Prevention
- Only enable cover-letter buttons for resumes with parent_id set.
- Visually distinguish base resumes from tailored resumes in lists.
- Route users into the tailor flow when they attempt generation on a base resume.
When it happens
Trigger: Requesting cover-letter generation for a base/original resume (created by upload, not by the tailor-to-job flow), i.e. resume.parent_id is null or missing.
Common situations: User clicks 'Generate cover letter' on an uploaded resume instead of a tailored variant; UI list mixes base and tailored resumes without labeling; older records created before the parent_id linkage was added.
Related errors
- Invalid improved resume data. Please retry preview.
- Preview required before confirmation. Please retry preview.
- Outreach message can only be generated for tailored resumes.
- Interview preparation can only be generated for tailored res
- Job description is only available for tailored resumes.
AI-assisted analysis of srbhr/Resume-Matcher@116f9cc3b0 (2026-08-28).
Data as JSON: /api/errors/e2d23797eace002b.
Report an issue: GitHub.