srbhr/Resume-Matcher · warning · HTTPException

Only resumes with 'failed' or 'processing' status can be ret

Error message

Only resumes with 'failed' or 'processing' status can be retried.

What it means

HTTP 400 raised by the resume retry endpoint (retry_processing) when the target resume's processing_status is not 'failed' or 'processing'. Retry only makes sense for resumes whose processing actually failed or is stuck mid-flight; resuming a completed ('completed') or fresh resume would duplicate work or corrupt state. The library throws this as a guard before invoking the AI re-parse pipeline.

Source

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

    if not await db.delete_resume(resume_id):
        raise HTTPException(status_code=404, detail="Resume not found")

    return {"message": "Resume deleted successfully"}


@router.post("/{resume_id}/retry-processing", response_model=ResumeUploadResponse)
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",

View on GitHub (pinned to 116f9cc3b0)

Solutions

  1. Check the resume's processing_status (GET resume detail) before calling the retry endpoint and only offer retry when it is 'failed' or 'processing'.
  2. If the resume is stuck in 'processing', wait for or investigate the background job; retry is only valid while it remains non-terminal.
  3. If the resume already completed successfully, re-upload or use the reprocess endpoint instead of retry.
  4. Refresh frontend status state (poll/websocket) so the retry button is disabled for ineligible resumes.

Example fix

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

// after: pre-check status
const r = await api.get(`/resumes/${id}`);
if (['failed', 'processing'].includes(r.data.processing_status)) {
  await api.post(`/resumes/${id}/retry`);
}
Defensive patterns

Strategy: validation

Validate before calling

const resume = await api.get(`/resumes/${id}`);
if (!['failed', 'processing'].includes(resume.data.processing_status)) {
  throw new Error(`Cannot retry: status is '${resume.data.processing_status}'`);
}

Type guard

const canRetry = (r) => r != null && ['failed', 'processing'].includes(r.processing_status);

Try / catch

try {
  await api.post(`/resumes/${id}/retry`);
} catch (e) {
  if (e.response?.status === 400) {
    console.warn('Resume not in a retryable state; refresh status.');
    await refreshResumeStatus(id);
  } else throw e;
}

Prevention

When it happens

Trigger: PATCH/POST to the resume retry endpoint with a resume_id whose stored processing_status is 'completed', 'pending', or any value other than 'failed' or 'processing'.

Common situations: User clicks a 'Retry' button on a successfully processed resume; double-clicking retry after the first retry already finished (status became 'completed'); frontend state stale relative to the DB; status field names changed in a schema migration so the check falls through.

Related errors


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