{"record":{"id":"581282ac3348d654","repo":"nexu-io/open-design","slug":"job-args-job-id-has-no-output-path","errorCode":null,"errorMessage":"job {args.job_id} has no output_path","messagePattern":"job (.+?) has no output_path","errorType":"exception","errorClass":"SystemExit","httpStatus":null,"severity":"error","filePath":"skills/hatch-pet/scripts/record_imagegen_result.py","lineNumber":198,"sourceCode":"\n    manifest_path = run_dir / \"imagegen-jobs.json\"\n    manifest = load_jobs(manifest_path)\n    job = find_job(manifest, args.job_id)\n\n    missing_deps = [\n        dep\n        for dep in job.get(\"depends_on\", [])\n        if isinstance(dep, str) and dep not in completed_job_ids(manifest)\n    ]\n    if missing_deps:\n        raise SystemExit(\n            f\"job {args.job_id} is not ready; missing dependency result(s): {', '.join(missing_deps)}\"\n        )\n    validate_required_grounding(job, run_dir)\n\n    output_raw = job.get(\"output_path\")\n    if not isinstance(output_raw, str):\n        raise SystemExit(f\"job {args.job_id} has no output_path\")\n    output = run_dir / output_raw\n    if output.exists() and not args.force:\n        raise SystemExit(f\"{output} already exists; pass --force to replace it\")\n\n    output.parent.mkdir(parents=True, exist_ok=True)\n    shutil.copy2(source, output)\n    metadata = image_metadata(output)\n\n    job[\"status\"] = \"complete\"\n    job[\"source_path\"] = str(source)\n    job[\"source_provenance\"] = source_provenance\n    job[\"source_sha256\"] = file_sha256(source)\n    job[\"output_sha256\"] = file_sha256(output)\n    if source_provenance == \"synthetic-test\":\n        job[\"synthetic_test_source\"] = True\n    else:\n        job.pop(\"synthetic_test_source\", None)\n    job[\"completed_at\"] = datetime.now(timezone.utc).isoformat()","sourceCodeStart":180,"sourceCodeEnd":216,"githubUrl":"https://github.com/nexu-io/open-design/blob/5be4028344c2eb4c667c5a97bda8f750c5597ef7/skills/hatch-pet/scripts/record_imagegen_result.py#L180-L216","documentation":"Raised in record_imagegen_result.py main() when job.get('output_path') is not a string. The recorder copies the source to run_dir/<output_path> and writes metadata there, so a missing/non-string output_path means the manifest job is malformed and cannot be recorded against.","triggerScenarios":"Job was defined without output_path; output_path is null or a number after a hand-edit; manifest schema drifted from what prepare produces.","commonSituations":"Manual job addition that omitted output_path; bad merge; older manifest format.","solutions":["Add a string output_path to the job, e.g. \"output_path\": \"decoded/idle.png\".","Re-run prepare_pet_run.py --force to regenerate well-formed jobs.","Validate: jq '.jobs[] | .output_path | type' imagegen-jobs.json (every entry should be 'string').","Restore the manifest from version control."],"exampleFix":"// before: {\"id\":\"idle\"}\n// after:  {\"id\":\"idle\",\"output_path\":\"decoded/idle.png\"}","handlingStrategy":"type-guard","validationCode":"output_raw = job.get(\"output_path\")\nif not isinstance(output_raw, str) or not output_raw:\n    raise SystemExit(f\"job {job.get('id')} has no string output_path\")","typeGuard":"def has_output_path(job: dict) -> bool:\n    return isinstance(job.get(\"output_path\"), str) and bool(job[\"output_path\"])","tryCatchPattern":null,"preventionTips":["Let prepare define output_path for every job.","Validate the manifest with jsonschema (output_path: required string).","Avoid adding jobs by hand without output_path."],"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"}