srbhr/Resume-Matcher · error · HTTPException

Failed to generate cover letter. Please try again.

Error message

Failed to generate cover letter. Please try again.

What it means

This 500 error is raised by the generate_cover_letter_endpoint when the call to generate_cover_letter() (an AI/LLM-backed helper) throws any exception. The endpoint wraps the generation call in a broad try/except, logs the underlying cause, and returns a generic retry-able message so internal AI errors are not leaked to the client.

Source

Thrown at apps/backend/app/routers/resumes.py:1827

    # Get resume data
    resume_data = resume.get("processed_data")
    if not resume_data:
        raise HTTPException(
            status_code=400,
            detail="Resume has no processed data. Please re-upload the resume.",
        )

    # Get language setting
    language = get_content_language()

    # Generate cover letter
    try:
        cover_letter_content = await generate_cover_letter(
            resume_data, job["content"], language
        )
    except Exception as e:
        logger.error(f"Cover letter generation failed: {e}")
        raise HTTPException(
            status_code=500,
            detail="Failed to generate cover letter. Please try again.",
        )

    # Save to resume record
    await db.update_resume(resume_id, {"cover_letter": cover_letter_content})

    return GenerateContentResponse(
        content=cover_letter_content,
        message="Cover letter generated successfully",
    )


@router.post("/{resume_id}/generate-outreach", response_model=GenerateContentResponse)
async def generate_outreach_endpoint(resume_id: str) -> GenerateContentResponse:
    """Generate an outreach message on-demand for an existing tailored resume.

    This endpoint allows users to generate a cold outreach message after a resume

View on GitHub (pinned to 116f9cc3b0)

Solutions

  1. Check backend logs for 'Cover letter generation failed: <e>' to see the real cause
  2. Verify the LLM provider API key and quota in the backend environment
  3. Retry the request — transient provider timeouts/rate limits usually resolve
  4. Reduce resume/job description size if the payload may exceed model limits

Example fix

// before
curl -X POST /api/resumes/{id}/cover-letter  # 500 generic
// after
# inspect server logs first, e.g.
docker logs backend | grep 'Cover letter generation failed'
Defensive patterns

Strategy: try-catch

Validate before calling

const resume = await getResume(resumeId);
const job = await getJob(jobId);
if (!resume?.processedData || !job?.content) throw new Error('Missing inputs for cover letter generation');

Try / catch

try {
  await api.generateCoverLetter(resumeId);
} catch (e) {
  if (e.response?.status === 500) {
    // inspect server logs / retry after checking LLM provider health
    await sleep(1000);
    return retryOnce(() => api.generateCoverLetter(resumeId));
  }
  throw e;
}

Prevention

When it happens

Trigger: POSTing to the cover-letter generation route with valid resume_id/job context, but generate_cover_letter() fails — e.g. LLM API timeout, rate limit, invalid API key, malformed resume_data, or content that the model rejects.

Common situations: Expired or missing LLM API credentials in the environment, upstream provider outage or 429 rate limiting, oversized resume/job-description content exceeding the model context window, or network egress blocked from the backend.

Related errors


AI-assisted analysis of srbhr/Resume-Matcher@116f9cc3b0 (2026-08-28). Data as JSON: /api/errors/6289efe71276b846. Report an issue: GitHub.