{"record":{"id":"21bad2fee3775e10","repo":"srbhr/Resume-Matcher","slug":"resume-has-no-stored-content-to-re-process","errorCode":null,"errorMessage":"Resume has no stored content to re-process.","messagePattern":"Resume has no stored content to re-process\\.","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"error","filePath":"apps/backend/app/routers/resumes.py","lineNumber":1697,"sourceCode":"async def retry_processing(resume_id: str) -> ResumeUploadResponse:\n    \"\"\"Retry AI processing for a failed or stuck resume.\n\n    Re-runs parse_resume_to_json() on the stored markdown content.\n    Works for resumes with processing_status == \"failed\" or \"processing\".\n    \"\"\"\n    resume = await db.get_resume(resume_id)\n    if not resume:\n        raise HTTPException(status_code=404, detail=\"Resume not found\")\n\n    if resume.get(\"processing_status\") not in (\"failed\", \"processing\"):\n        raise HTTPException(\n            status_code=400,\n            detail=\"Only resumes with 'failed' or 'processing' status can be retried.\",\n        )\n\n    markdown_content = resume.get(\"content\", \"\")\n    if not markdown_content:\n        raise HTTPException(\n            status_code=400,\n            detail=\"Resume has no stored content to re-process.\",\n        )\n\n    try:\n        processed_data = await parse_resume_to_json(markdown_content)\n        await db.update_resume(\n            resume_id,\n            {\n                \"processed_data\": processed_data,\n                \"processing_status\": \"ready\",\n            },\n        )\n        return ResumeUploadResponse(\n            message=\"Resume processing succeeded on retry\",\n            request_id=str(uuid4()),\n            resume_id=resume_id,\n            processing_status=\"ready\",","sourceCodeStart":1679,"sourceCodeEnd":1715,"githubUrl":"https://github.com/srbhr/Resume-Matcher/blob/116f9cc3b00e1ac91734a6c2679bf41ea64a0edc/apps/backend/app/routers/resumes.py#L1679-L1715","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Re-upload the resume file so content (markdown) is stored, then retry processing.","Inspect the resume record (GET resume) to confirm 'content' is non-empty before retrying.","Fix the upload path that created the resume row without persisting content.","If content was lost in a migration, restore it from object storage / original file."],"exampleFix":"// before\nawait api.post(`/resumes/${id}/retry`);\n\n// after\nconst r = await api.get(`/resumes/${id}`);\nif (!r.data.content) {\n  await reuploadResume(id, file); // restore stored markdown first\n}\nawait api.post(`/resumes/${id}/retry`);","handlingStrategy":"validation","validationCode":"const resume = await api.get(`/resumes/${id}`);\nif (!resume.data.content) {\n  throw new Error('Resume has no stored content; re-upload required before retry.');\n}","typeGuard":"const hasContent = (r) => typeof r?.content === 'string' && r.content.trim().length > 0;","tryCatchPattern":"try {\n  await api.post(`/resumes/${id}/retry`);\n} catch (e) {\n  if (e.response?.status === 400 && /no stored content/.test(e.response.data?.detail ?? '')) {\n    await promptReupload(id);\n  } else throw e;\n}","preventionTips":["Verify content persisted (non-empty) after upload before marking the resume ready.","Alert on resumes whose content is null but a processing status is set.","Keep the original file in object storage so content can be restored."],"tags":["http-400","missing-data","resume-processing"],"backgroundTag":"missing-resume-content","analyzedSha":"116f9cc3b00e1ac91734a6c2679bf41ea64a0edc","analyzedAt":"2026-08-28T22:51:40.999Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}