srbhr/Resume-Matcher · error · ValueError
Original resume missing personalInfo
Error message
Original resume missing personalInfo
What it means
Part of the JSON-008 hardening in _validate_confirm_payload: before persisting a tailored resume, the confirm endpoint compares the original stored resume's processed_data.personalInfo with the improved data's personalInfo. If the original resume has no personalInfo key (or it is null), this ValueError is raised because the immutability check cannot be performed. The endpoint converts it into an HTTP 400 for the client.
Source
Thrown at apps/backend/app/routers/resumes.py:534
except Exception as e:
logger.warning("Skipping resume diff due to calculation failure: %s", e)
return None, None, f"calculation_error: {str(e)}"
def _validate_confirm_payload(
original_data: dict[str, Any] | None,
improved_data: dict[str, Any],
) -> None:
if not original_data:
logger.warning(
"Skipping confirm payload validation; structured resume data unavailable."
)
return
original_info = original_data.get("personalInfo")
improved_info = improved_data.get("personalInfo")
# JSON-008: Explicit null checks with clear error messages
if original_info is None:
raise ValueError("Original resume missing personalInfo")
if improved_info is None:
raise ValueError("Improved resume missing personalInfo")
if not isinstance(original_info, dict):
raise ValueError(
f"Original personalInfo is not a dict: {type(original_info).__name__}"
)
if not isinstance(improved_info, dict):
raise ValueError(
f"Improved personalInfo is not a dict: {type(improved_info).__name__}"
)
fields = set(original_info.keys()) | set(improved_info.keys())
mismatches = [
field
for field in sorted(fields)
if _normalize_personal_info_value(original_info.get(field))
!= _normalize_personal_info_value(improved_info.get(field))
]
if mismatches:View on GitHub (pinned to 116f9cc3b0)
Solutions
- Re-upload the resume or call /{id}/retry-processing so processed_data is regenerated with a personalInfo object
- Backfill personalInfo in the stored processed_data via PATCH /resumes/{id}
- Confirm against a different (valid) master resume
Example fix
// before: stored JSON resume without personalInfo
{"personalInfo": null, "summary": "..."}
// after: backfilled processed_data
{"personalInfo": {"name": "Jane Doe", "email": "jane@example.com", "phone": "+1...", "location": "..."}, "summary": "..."} Defensive patterns
Strategy: validation
Validate before calling
// client: ensure the resume has personalInfo before confirming
def assert_confirmable(original: dict):
if not isinstance(original.get("personalInfo"), dict):
raise ValueError("stored resume lacks personalInfo; re-upload or retry-processing first") Type guard
def has_personal_info(data: dict) -> bool:
return isinstance(data.get("personalInfo"), dict) Try / catch
try:
resp = api.post('/resumes/improve/confirm', payload)
except HTTPError as e:
if e.response.status_code == 400 and 'missing personalInfo' in e.response.text:
trigger_reprocess(resume_id) # regenerate processed_data Prevention
- Re-upload or retry-processing legacy resumes imported from database.json before tailoring them
- Never hand-edit processed_data in SQLite
- Keep personalInfo present in any JSON resume uploads
When it happens
Trigger: POST /resumes/improve/confirm with a resume_id whose stored processed_data lacks personalInfo or has it explicitly set to null — typical for older records parsed before personalInfo was part of the schema, or JSON resumes uploaded without a personalInfo object.
Common situations: Legacy database rows migrated from database.json with a partial schema; JSON-uploaded resumes missing the personalInfo field; data edited directly in SQLite removing the key.
Understand the failure class
Background: "Missing required field" and "field is required" errors: why libraries reject payloads that omit mandatory fields — this error's family across 20 libraries.
Related errors
- Improved resume missing personalInfo
- personalInfo fields changed: {', '.join(mismatches)}
- Original personalInfo is not a dict: {type(original_info).__
- Improved personalInfo is not a dict: {type(improved_info).__
- ${message = data.detail or Failed to update LLM config (stat
AI-assisted analysis of srbhr/Resume-Matcher@116f9cc3b0 (2026-08-28).
Data as JSON: /api/errors/b53c5ed6f2487b51.
Report an issue: GitHub.