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 manifest_jobs in generate_pet_images.py when imagegen-jobs.json parses but its 'jobs' field is not a list. This is the same schema invariant enforced by finalize_pet_run.py (error 632), checked here so the fallback generator fails early before any API call.

Source

Thrown at skills/hatch-pet/scripts/generate_pet_images.py:51

        return ALL_STATES
    states = [item.strip() for item in raw.split(",") if item.strip()]
    unknown = sorted(set(states) - set(ALL_STATES))
    if unknown:
        raise SystemExit(f"unknown state(s): {', '.join(unknown)}")
    return states


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 manifest_jobs(manifest: dict[str, object]) -> list[dict[str, object]]:
    jobs = manifest.get("jobs")
    if not isinstance(jobs, list):
        raise SystemExit("invalid imagegen-jobs.json: jobs must be a list")
    return [job for job in jobs if isinstance(job, dict)]


def select_jobs(
    manifest: dict[str, object],
    *,
    states: list[str],
    skip_base: bool,
    job_ids: list[str],
) -> list[dict[str, object]]:
    selected_ids = set(job_ids)
    if not selected_ids:
        if not skip_base:
            selected_ids.add("base")
        selected_ids.update(states)
    selected = [job for job in manifest_jobs(manifest) if job.get("id") in selected_ids]
    missing = selected_ids - {str(job.get("id")) for job in selected}
    if missing:

View on GitHub (pinned to 5be4028344)

Solutions

  1. Ensure imagegen-jobs.json has a top-level 'jobs' array of objects.
  2. Regenerate the manifest from the job-creation step.
  3. Validate with a JSON schema or a one-line type check before running generate_pet_images.py.

Example fix

// before (imagegen-jobs.json)
{"jobs":null}
// after
{"jobs":[{"id":"base",...}]}
Defensive patterns

Strategy: type-guard

Validate before calling

manifest = json.loads(Path('imagegen-jobs.json').read_text())
jobs = manifest.get('jobs')
assert isinstance(jobs, list), 'jobs must be a list'

Type guard

def is_jobs_array(manifest: object) -> bool:
    return isinstance(manifest, dict) and isinstance(manifest.get('jobs'), list)

Prevention

When it happens

Trigger: manifest.get('jobs') is not a list (dict, string, null, etc.) in a manifest that otherwise parses as JSON.

Common situations: Corrupted or hand-edited manifest where the jobs array became an object; schema drift; a write that nulled the field.

Related errors


AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12). Data as JSON: /api/errors/623a2a4c7f9baba0. Report an issue: GitHub.