nexu-io/open-design · error · SystemExit
invalid imagegen-jobs.json: jobs must be a list
Error message
invalid imagegen-jobs.json: jobs must be a list
What it means
Raised by jobs() in pet_job_status.py (and the parallel check in generate_pet_images.py:51) when imagegen-jobs.json parses but its top-level jobs field is not a list. The contract is {schema_version, jobs: [...]}, so a non-list jobs value is treated as corruption.
Source
Thrown at skills/hatch-pet/scripts/pet_job_status.py:21
from __future__ import annotations
import argparse
import json
from pathlib import Path
def load_manifest(run_dir: Path) -> dict[str, object]:
path = run_dir / "imagegen-jobs.json"
if not path.exists():
raise SystemExit(f"job manifest not found: {path}")
return json.loads(path.read_text(encoding="utf-8"))
def jobs(manifest: dict[str, object]) -> list[dict[str, object]]:
raw = manifest.get("jobs")
if not isinstance(raw, list):
raise SystemExit("invalid imagegen-jobs.json: jobs must be a list")
return [job for job in raw if isinstance(job, dict)]
def completed_ids(manifest: dict[str, object]) -> set[str]:
return {
str(job["id"])
for job in jobs(manifest)
if job.get("status") == "complete" and isinstance(job.get("id"), str)
}
def missing_deps(job: dict[str, object], completed: set[str]) -> list[str]:
deps = job.get("depends_on", [])
if not isinstance(deps, list):
return []
return [dep for dep in deps if isinstance(dep, str) and dep not in completed]
View on GitHub (pinned to 5be4028344)
Solutions
- Open imagegen-jobs.json and confirm jobs is a JSON array of job objects.
- If it is keyed by id, convert to a list, or regenerate with prepare_pet_run.py.
- Validate JSON: python -c "import json; d=json.load(open('imagegen-jobs.json')); print(type(d['jobs']).__name__)" should print list.
- Re-run the status/generation command.
Example fix
// before (manifest)
{"jobs": {"base": {...}, "idle": {...}}}
// after
{"schema_version": 1, "jobs": [{"id": "base", ...}, {"id": "idle", ...}]} Defensive patterns
Strategy: type-guard
Validate before calling
def assert_jobs_list(manifest: dict) -> list:
raw = manifest.get("jobs")
if not isinstance(raw, list):
raise SystemExit("invalid imagegen-jobs.json: jobs must be a list")
return raw Type guard
from typing import Any
def has_jobs_list(manifest: Any) -> bool:
return isinstance(manifest, dict) and isinstance(manifest.get("jobs"), list) Prevention
- Treat imagegen-jobs.json as generated; regenerate with prepare_pet_run.py instead of restructuring.
- Validate with jsonschema: jobs must be an array of objects.
- Keep schema_version bumped when the manifest shape changes.
When it happens
Trigger: imagegen-jobs.json was hand-edited so jobs is a dict or object keyed by id; a partial write left jobs as null; a different schema version nested jobs elsewhere.
Common situations: Restructuring the manifest to {jobs: {idle: {...}}} instead of a list; truncated write from a crashed run; manifest produced by an incompatible tool.
Related errors
- job {job.get('id')} has invalid input_images
- job {job.get('id')} has invalid input image entry
- job {job_id} is missing prompt_file or output_path
- path traversal detected in input_images for job {job.get('id
- path traversal detected in prompt_file for job {job_id}
AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12).
Data as JSON: /api/errors/3a8cb027612ceae6.
Report an issue: GitHub.