{"record":{"id":"85d7e0635b812263","repo":"nexu-io/open-design","slug":"unknown-job-id-job-id-85d7e0","errorCode":null,"errorMessage":"unknown job id: {job_id}","messagePattern":"unknown job id: (.+?)","errorType":"exception","errorClass":"SystemExit","httpStatus":null,"severity":"error","filePath":"skills/hatch-pet/scripts/record_imagegen_result.py","lineNumber":36,"sourceCode":"\ndef load_jobs(path: Path) -> dict[str, object]:\n    if not path.exists():\n        raise SystemExit(f\"job manifest not found: {path}\")\n    return json.loads(path.read_text(encoding=\"utf-8\"))\n\n\ndef job_list(manifest: dict[str, object]) -> list[dict[str, object]]:\n    jobs = manifest.get(\"jobs\")\n    if not isinstance(jobs, list):\n        raise SystemExit(\"invalid imagegen-jobs.json: jobs must be a list\")\n    return [job for job in jobs if isinstance(job, dict)]\n\n\ndef find_job(manifest: dict[str, object], job_id: str) -> dict[str, object]:\n    for job in job_list(manifest):\n        if job.get(\"id\") == job_id:\n            return job\n    raise SystemExit(f\"unknown job id: {job_id}\")\n\n\ndef image_metadata(path: Path) -> dict[str, object]:\n    with Image.open(path) as image:\n        image.verify()\n    with Image.open(path) as image:\n        return {\n            \"width\": image.width,\n            \"height\": image.height,\n            \"mode\": image.mode,\n            \"format\": image.format,\n        }\n\n\ndef file_sha256(path: Path) -> str:\n    digest = hashlib.sha256()\n    with path.open(\"rb\") as file:\n        for chunk in iter(lambda: file.read(1024 * 1024), b\"\"):","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/nexu-io/open-design/blob/5be4028344c2eb4c667c5a97bda8f750c5597ef7/skills/hatch-pet/scripts/record_imagegen_result.py#L18-L54","documentation":"Raised by find_job() in record_imagegen_result.py when no job in the manifest has id == --job-id. The recorder must update a specific job record (status, hashes, grounding), so an unmatched job id aborts before touching the manifest.","triggerScenarios":"Passing a --job-id that does not exist in imagegen-jobs.json; typo in the id; manifest was regenerated with a different row set; --job-id from a different pet's run.","commonSituations":"Recording output for a row that was renamed since prepare; copy-pasting a job id from another run; case mismatch (Idle vs idle).","solutions":["List valid ids: jq '.jobs[].id' run_dir/imagegen-jobs.json.","Pass the exact matching --job-id (watch case and hyphenation).","If the id should exist, re-run prepare_pet_run.py --force with the intended rows.","Confirm --run-dir matches the run that owns the job id."],"exampleFix":"# before\nrecord_imagegen_result.py --job-id Idle --source ig_001.png\n# after\nrecord_imagegen_result.py --job-id idle --source ig_001.png","handlingStrategy":"validation","validationCode":"ids = {j.get(\"id\") for j in job_list(manifest)}\nif args.job_id not in ids:\n    raise SystemExit(f\"--job-id {args.job_id} not in {sorted(ids)}\")","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pull --job-id directly from jq '.jobs[].id' to avoid typos.","Keep job ids lowercase-kebab and stable across regenerations.","Record jobs in a deterministic order so id drift is obvious."],"tags":["data-validation","cli","hatch-pet","schema"],"backgroundTag":null,"analyzedSha":"5be4028344c2eb4c667c5a97bda8f750c5597ef7","analyzedAt":"2026-08-12T12:03:58.812Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}