{"record":{"id":"9e7ebbbd9dd0af2d","repo":"srbhr/Resume-Matcher","slug":"job-not-found","errorCode":null,"errorMessage":"Job not found","messagePattern":"Job not found","errorType":"http","errorClass":"HTTPException","httpStatus":404,"severity":"error","filePath":"apps/backend/app/routers/jobs.py","lineNumber":48,"sourceCode":"        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}\")\nasync def get_job(job_id: str) -> dict:\n    \"\"\"Get job description by ID.\"\"\"\n    job = await db.get_job(job_id)\n\n    if not job:\n        raise HTTPException(status_code=404, detail=\"Job not found\")\n\n    return job\n","sourceCodeStart":30,"sourceCodeEnd":51,"githubUrl":"https://github.com/srbhr/Resume-Matcher/blob/116f9cc3b00e1ac91734a6c2679bf41ea64a0edc/apps/backend/app/routers/jobs.py#L30-L51","documentation":"A 404 from GET /jobs/{job_id} when no job with that ID exists in the database. get_job simply forwards db.get_job's result; a falsy result (None) becomes 404. Also surfaces indirectly via callers like cover-letter and improve-resume endpoints that depend on a valid job_id.","triggerScenarios":"Requesting a job_id that was never created, was deleted, or contains a typo; using a job_id from another environment/database; passing an expired ID after DB cleanup.","commonSituations":"Client cached a job_id whose record was purged; copying an ID from staging into a production call; truncating the jobs table during development and reusing old IDs.","solutions":["Verify the job_id exists (list jobs or check the DB) before calling the endpoint","Re-upload the job description to obtain a fresh job_id if the record was deleted","Confirm you are pointing at the correct environment/database","Log the failing job_id and fix the client source that produced it"],"exampleFix":"// before\nconst job = await api.get(`/jobs/${jobId}`);\n// after\nconst res = await api.get(`/jobs/${jobId}`).catch(e =>\n  e.response?.status === 404 ? null : Promise.reject(e));\nif (!res) {\n  const created = await uploadJob(text);\n  job = created;\n}","handlingStrategy":"try-catch","validationCode":"// Verify the ID exists before dependent calls\nconst exists = await api.get(`/jobs/${jobId}`).then(() => true).catch(e => e.response?.status === 404 ? false : Promise.reject(e));\nif (!exists) throw new Error(`Job ${jobId} does not exist`);","typeGuard":"function isValidJobId(id) {\n  return typeof id === 'string' && id.trim().length > 0; // plus UUID check if applicable\n}\nconst isUuid = id => /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(id);","tryCatchPattern":"try {\n  job = await api.get(`/jobs/${jobId}`);\n} catch (e) {\n  if (e.response?.status === 404) {\n    job = await createJobFromText(savedText); // re-upload to obtain a fresh job_id\n  } else throw e;\n}","preventionTips":["Store job_ids only from the same environment that issued them","Persist job_ids alongside the resume they were created for","Handle 404 by re-uploading the original job text rather than failing","Never hand-edit or truncate job IDs"],"tags":["http","not-found","rest","fastapi"],"backgroundTag":"resource-not-found","analyzedSha":"116f9cc3b00e1ac91734a6c2679bf41ea64a0edc","analyzedAt":"2026-08-28T22:51:40.999Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}