srbhr/Resume-Matcher · error · HTTPException

Failed to delete applications. Please try again.

Error message

Failed to delete applications. Please try again.

What it means

This 500 HTTPException is raised by bulk_delete_applications when db.bulk_delete_applications(request.application_ids) throws. It wraps any persistence-layer exception during multi-delete and hides details from the client while logging server-side. Note the non-transactional semantics: some documents may have been deleted before the failure.

Source

Thrown at apps/backend/app/routers/applications.py:172

    """Delete a card."""
    try:
        deleted = await db.delete_application(application_id)
    except Exception as e:
        logger.error("Failed to delete application %s: %s", application_id, e)
        raise HTTPException(status_code=500, detail="Failed to delete application. Please try again.")
    if not deleted:
        raise HTTPException(status_code=404, detail="Application not found")
    return ApplicationActionResponse(message="Application deleted", affected=1)


@router.post("/bulk-delete", response_model=ApplicationActionResponse)
async def bulk_delete_applications(request: BulkDelete) -> ApplicationActionResponse:
    """Delete many cards."""
    try:
        deleted = await db.bulk_delete_applications(request.application_ids)
    except Exception as e:
        logger.error("Failed to bulk-delete applications: %s", e)
        raise HTTPException(status_code=500, detail="Failed to delete applications. Please try again.")
    return ApplicationActionResponse(message=f"Deleted {deleted} application(s)", affected=deleted)


async def _extract_company_role(job_description: str) -> dict[str, str | None]:
    """Best-effort company/role extraction for the manual-add path.

    Reuses the cached keyword-extraction pass; falls back to blank (editable)
    on any failure so a flaky LLM never blocks card creation. LLM output isn't
    guaranteed to be a string, so values are type-guarded before ``.strip()``.
    """
    try:
        keywords = await extract_job_keywords(job_description)
        raw_company = keywords.get("company")
        raw_role = keywords.get("role")
        return {
            "company": (raw_company.strip() if isinstance(raw_company, str) else "") or None,
            "role": (raw_role.strip() if isinstance(raw_role, str) else "") or None,
        }

View on GitHub (pinned to 116f9cc3b0)

Solutions

  1. Check backend logs for 'Failed to bulk-delete applications' for the root cause
  2. Validate/normalize every id in application_ids before sending (correct type/format)
  3. Retry with a smaller batch to isolate a problematic id
  4. Verify database connectivity and health

Example fix

// before
await api.bulkDeleteApplications(ids)
// after
const valid = ids.filter((id) => /^[a-f\d]{24}$/i.test(id))
if (valid.length !== ids.length) console.warn('dropping invalid ids')
await api.bulkDeleteApplications(valid)
Defensive patterns

Strategy: validation

Validate before calling

const valid = ids.filter(id => typeof id === 'string' && id.length > 0)
if (valid.length === 0) throw new Error('no valid ids to delete')

Try / catch

try {
  await api.bulkDeleteApplications(ids)
} catch (e) {
  if (e.response?.status === 500) {
    // fall back to per-id deletes to salvage partial progress
    await Promise.allSettled(ids.map(id => api.deleteApplication(id)))
  }
}

Prevention

When it happens

Trigger: POST /applications/bulk-delete with an application_ids list that causes the db layer to raise: DB connection failure, invalid id format in the list causing driver cast errors, or oversized delete query.

Common situations: Batch contains one malformed/legacy id that breaks the whole delete, MongoDB timeout on very large batches, or DB outage mid-request.

Related errors


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