srbhr/Resume-Matcher · error · ValueError
Resume content is empty after text extraction.
Error message
Resume content is empty after text extraction.
What it means
parse_resume_to_json requires non-empty markdown resume text because it will be sent to the LLM for structuring. If markdown_text is None, empty, or whitespace-only after upstream text extraction, it raises this ValueError instead of making a doomed LLM call.
Source
Thrown at apps/backend/app/services/parser.py:158
finally:
tmp_path.unlink(missing_ok=True)
async def parse_resume_to_json(markdown_text: str) -> dict[str, Any]:
"""Parse resume markdown to structured JSON using LLM.
After LLM parsing, patches any year-only dates with month-inclusive
dates extracted from the raw markdown. This ensures months are never
lost regardless of LLM behavior.
Args:
markdown_text: Resume content in markdown format
Returns:
Structured resume data matching ResumeData schema
"""
if not markdown_text or not markdown_text.strip():
raise ValueError("Resume content is empty after text extraction.")
prompt = PARSE_RESUME_PROMPT.format(
schema=RESUME_SCHEMA_EXAMPLE,
resume_text=markdown_text,
)
config = get_llm_config()
model_name = get_model_name(config)
result = await complete_json(
prompt=prompt,
system_prompt="You are a JSON extraction engine. Output only valid JSON, no explanations.",
max_tokens=get_safe_max_tokens(model_name),
retries=3,
)
# Patch dates: restore months the LLM may have dropped
result = restore_dates_from_markdown(result, markdown_text)
View on GitHub (pinned to 116f9cc3b0)
Solutions
- Verify the uploaded file has extractable text (e.g. run pdftotext / inspect extraction output) before parsing
- Reject image-only/scanned PDFs at upload and ask the user for a text-based file, or enable OCR preprocessing
- Check the file isn't empty/corrupt at upload time and return a 400/422 with a clear message
- Log extraction output size to distinguish extractor failures from genuinely empty documents
Example fix
// before
text = extract_text(upload.file)
await parse_resume_to_json(text) # ValueError if blank
// after
text = extract_text(upload.file)
if not text or not text.strip():
raise HTTPException(422, "Could not extract text from the uploaded resume (scanned PDF?)")
await parse_resume_to_json(text) Defensive patterns
Strategy: try-catch
Validate before calling
def extraction_ok(text: str | None) -> bool:
return bool(text and text.strip()) Type guard
def has_extractable_text(v: object) -> TypeGuard[str]:
return isinstance(v, str) and v.strip() != "" Try / catch
try:
data = await parse_resume_to_json(markdown_text)
except ValueError as e:
if "empty after text extraction" in str(e):
raise HTTPException(422, "No readable text in the uploaded resume; try a text-based PDF/DOCX.") from e
raise Prevention
- Detect scanned/image-only PDFs at upload (no text layer) and require OCR or a different file
- Check file size > 0 and extractor output length before parsing
- Show a clear upload error instead of proceeding to LLM parsing
- Log extraction char counts to spot failing extractors
When it happens
Trigger: Uploading a resume file whose extraction produced no text (empty file, scanned/image-only PDF with no OCR text, corrupted docx), or calling parse_resume_to_json directly with ""/None; raised in paths reached via upload_resume and retry_processing.
Common situations: User uploads a scanned PDF (image-only, no text layer), a zero-byte file, or an unsupported format that the extractor silently returns empty for; OCR not configured.
Related errors
- Invalid file type: {file.content_type}. Allowed: PDF, DOC, D
- File too large. Maximum size: {MAX_FILE_SIZE // (1024 * 1024
- Empty file
- Failed to parse document. Please ensure it's a valid PDF or
AI-assisted analysis of srbhr/Resume-Matcher@116f9cc3b0 (2026-08-28).
Data as JSON: /api/errors/9e4c6f28f581d4fe.
Report an issue: GitHub.