nexu-io/open-design · error · SystemExit

job {job.get('id')} has invalid input_images

Error message

job {job.get('id')} has invalid input_images

What it means

Raised by path_list when a job's input_images field is present but is not a list. The generator iterates input_images to attach reference images to the OpenAI images/edits request, so any non-list shape is unrecoverable.

Source

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

    canonical.parent.mkdir(parents=True, exist_ok=True)
    shutil.copy2(output_image, canonical)
    reference = {
        "path": CANONICAL_BASE_PATH,
        "source_job": "base",
        "sha256": file_sha256(canonical),
    }
    manifest["canonical_identity_reference"] = reference
    request_path = run_dir / "pet_request.json"
    if request_path.exists():
        request = json.loads(request_path.read_text(encoding="utf-8"))
        request["canonical_identity_reference"] = reference
        request_path.write_text(json.dumps(request, indent=2) + "\n", encoding="utf-8")


def path_list(run_dir: Path, job: dict[str, object]) -> list[Path]:
    inputs = job.get("input_images")
    if not isinstance(inputs, list):
        raise SystemExit(f"job {job.get('id')} has invalid input_images")
    paths = []
    for item in inputs:
        if not isinstance(item, dict) or not isinstance(item.get("path"), str):
            raise SystemExit(f"job {job.get('id')} has invalid input image entry")
        path = (run_dir / item["path"]).resolve()
        if not path.is_relative_to(run_dir):
            raise SystemExit(f"path traversal detected in input_images for job {job.get('id')}")
        if not path.is_file():
            raise SystemExit(f"input image for job {job.get('id')} not found: {path}")
        paths.append(path)
    return paths


def main() -> None:
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("--run-dir", required=True)
    parser.add_argument("--model", default="gpt-image-2")
    parser.add_argument("--size", default="1024x1024")

View on GitHub (pinned to 5be4028344)

Solutions

  1. Open run_dir/imagegen-jobs.json and find the job whose id matches the message.
  2. Fix input_images to a list of {"path": "<relative>", "role": "..."} objects, matching the shape prepare_pet_run.py writes.
  3. If unsure of the intended inputs, regenerate the run dir with prepare_pet_run.py instead of patching by hand.
  4. Rerun generate_pet_images.py scoped to --job-id <id>.

Example fix

// before (manifest)
"input_images": "references/canonical-base.png"

// after
"input_images": [
  {"path": "references/canonical-base.png", "role": "canonical identity reference"}
]
Defensive patterns

Strategy: validation

Validate before calling

def assert_input_images(job: dict) -> list:
    inputs = job.get("input_images")
    if not isinstance(inputs, list):
        raise SystemExit(f"job {job.get('id')} has invalid input_images")
    return inputs

Type guard

from typing import Any

def is_string_list(value: Any) -> bool:
    return isinstance(value, list)

Prevention

When it happens

Trigger: The imagegen-jobs.json manifest for the job has input_images set to a string, dict, number, or null (e.g. someone hand-edited the manifest, or an earlier run wrote input_images as a single object instead of a list).

Common situations: Manual edits to imagegen-jobs.json; a different version of prepare_pet_run.py that emits a different input_images shape; corrupt/partial manifest from an interrupted run.

Related errors


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