{"record":{"id":"5ccead959a572111","repo":"srbhr/Resume-Matcher","slug":"empty-job-description","errorCode":null,"errorMessage":"Empty job description","messagePattern":"Empty job description","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"warning","filePath":"apps/backend/app/routers/jobs.py","lineNumber":24,"sourceCode":"from app.schemas import JobUploadRequest, JobUploadResponse\n\nrouter = APIRouter(prefix=\"/jobs\", tags=[\"Jobs\"])\n\n\n@router.post(\"/upload\", response_model=JobUploadResponse)\nasync def upload_job_descriptions(request: JobUploadRequest) -> JobUploadResponse:\n    \"\"\"Upload one or more job descriptions.\n\n    Stores the raw text for later use in resume tailoring.\n    Returns an array of job_ids corresponding to the input array.\n    \"\"\"\n    if not request.job_descriptions:\n        raise HTTPException(status_code=400, detail=\"No job descriptions provided\")\n\n    job_ids = []\n    for jd in request.job_descriptions:\n        if not jd.strip():\n            raise HTTPException(status_code=400, detail=\"Empty job description\")\n\n        job = await db.create_job(\n            content=jd.strip(),\n            resume_id=request.resume_id,\n        )\n        job_ids.append(job[\"job_id\"])\n\n    return JobUploadResponse(\n        message=\"data successfully processed\",\n        job_id=job_ids,\n        request={\n            \"job_descriptions\": request.job_descriptions,\n            \"resume_id\": request.resume_id,\n        },\n    )\n\n\n@router.get(\"/{job_id}\")","sourceCodeStart":6,"sourceCodeEnd":42,"githubUrl":"https://github.com/srbhr/Resume-Matcher/blob/116f9cc3b00e1ac91734a6c2679bf41ea64a0edc/apps/backend/app/routers/jobs.py#L6-L42","documentation":"A 400 Bad Request from upload_job_descriptions raised when an individual entry in job_descriptions is empty or whitespace-only. Unlike error 102 (whole list missing), this fires per-item inside the loop before the job is stored.","triggerScenarios":"A job_descriptions array containing '' or '   ' entries, typically from splitting pasted text on blank lines or extra newlines; a UI allowing an empty job slot to be submitted.","commonSituations":"User pastes multiple job descriptions separated by blank lines and the client splits naively; trailing separators produce an empty final element; whitespace-only paste from a PDF copy.","solutions":["Trim and filter out empty strings from job_descriptions before uploading","Fix the client-side split logic to drop blank segments (split on /\\n\\s*\\n/ and filter)","If the backend contract should tolerate blanks, sanitize server-side or document the requirement"],"exampleFix":"// before\nconst jds = pasted.split('\\n---\\n');\nawait api.post('/jobs/upload', { job_descriptions: jds });\n// after\nconst jds = pasted.split(/\\n\\s*---\\s*\\n/).map(s => s.trim()).filter(Boolean);\nawait api.post('/jobs/upload', { job_descriptions: jds });","handlingStrategy":"validation","validationCode":"function sanitizeJobDescriptions(texts) {\n  const cleaned = texts.map(t => String(t).trim()).filter(t => t.length > 0);\n  if (cleaned.length !== texts.length) console.warn('Dropped empty job description entries');\n  return cleaned;\n}","typeGuard":"function allNonEmptyStrings(arr) {\n  return Array.isArray(arr) && arr.length > 0 && arr.every(s => typeof s === 'string' && s.trim().length > 0);\n}","tryCatchPattern":"try {\n  await api.post('/jobs/upload', { job_descriptions: jds });\n} catch (e) {\n  if (e.response?.status === 400 && e.response.data?.detail === 'Empty job description') {\n    jds = sanitizeJobDescriptions(jds); // then retry\n  } else throw e;\n}","preventionTips":["Trim every entry before uploading","Split pasted text on blank-line separators, not raw newlines","Filter out whitespace-only segments after splitting","Show per-field client validation so users see which job entry is empty"],"tags":["http","validation","bad-request","fastapi"],"backgroundTag":"empty-required-field","analyzedSha":"116f9cc3b00e1ac91734a6c2679bf41ea64a0edc","analyzedAt":"2026-08-28T22:51:40.999Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}