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

  1. Re-upload the resume or call /{id}/retry-processing so processed_data is regenerated with a personalInfo object
  2. Backfill personalInfo in the stored processed_data via PATCH /resumes/{id}
  3. 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

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


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