srbhr/Resume-Matcher · error · HTTPException

Resume has no stored content to re-process.

Error message

Resume has no stored content to re-process.

What it means

HTTP 400 raised by retry_processing when the resume passes the status check but has an empty 'content' field — there is no stored markdown to feed back into parse_resume_to_json. Without the original markdown the AI re-parse cannot run, so the endpoint refuses rather than silently producing an empty result.

Source

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

async def retry_processing(resume_id: str) -> ResumeUploadResponse:
    """Retry AI processing for a failed or stuck resume.

    Re-runs parse_resume_to_json() on the stored markdown content.
    Works for resumes with processing_status == "failed" or "processing".
    """
    resume = await db.get_resume(resume_id)
    if not resume:
        raise HTTPException(status_code=404, detail="Resume not found")

    if resume.get("processing_status") not in ("failed", "processing"):
        raise HTTPException(
            status_code=400,
            detail="Only resumes with 'failed' or 'processing' status can be retried.",
        )

    markdown_content = resume.get("content", "")
    if not markdown_content:
        raise HTTPException(
            status_code=400,
            detail="Resume has no stored content to re-process.",
        )

    try:
        processed_data = await parse_resume_to_json(markdown_content)
        await db.update_resume(
            resume_id,
            {
                "processed_data": processed_data,
                "processing_status": "ready",
            },
        )
        return ResumeUploadResponse(
            message="Resume processing succeeded on retry",
            request_id=str(uuid4()),
            resume_id=resume_id,
            processing_status="ready",

View on GitHub (pinned to 116f9cc3b0)

Solutions

  1. Re-upload the resume file so content (markdown) is stored, then retry processing.
  2. Inspect the resume record (GET resume) to confirm 'content' is non-empty before retrying.
  3. Fix the upload path that created the resume row without persisting content.
  4. If content was lost in a migration, restore it from object storage / original file.

Example fix

// before
await api.post(`/resumes/${id}/retry`);

// after
const r = await api.get(`/resumes/${id}`);
if (!r.data.content) {
  await reuploadResume(id, file); // restore stored markdown first
}
await api.post(`/resumes/${id}/retry`);
Defensive patterns

Strategy: validation

Validate before calling

const resume = await api.get(`/resumes/${id}`);
if (!resume.data.content) {
  throw new Error('Resume has no stored content; re-upload required before retry.');
}

Type guard

const hasContent = (r) => typeof r?.content === 'string' && r.content.trim().length > 0;

Try / catch

try {
  await api.post(`/resumes/${id}/retry`);
} catch (e) {
  if (e.response?.status === 400 && /no stored content/.test(e.response.data?.detail ?? '')) {
    await promptReupload(id);
  } else throw e;
}

Prevention

When it happens

Trigger: Calling the retry endpoint on a 'failed'/'processing' resume whose 'content' (markdown) column is null, missing, or an empty string — e.g. the record was created but content upload/persist failed before processing started.

Common situations: Partial DB write during initial upload (row created, content save failed); data migration that dropped the content column; manual DB cleanup removed content; resume imported from a legacy source without markdown stored.

Related errors


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