nexu-io/open-design · error · SystemExit

job {job_id} has invalid secondary fallback provenance

Error message

job {job_id} has invalid secondary fallback provenance

What it means

Raised by validate_completed_job_source when a job has secondary_fallback truthy but source_provenance != 'secondary-fallback-image-api'. The two fields must agree: a secondary-fallback row is one generated through generate_pet_images.py's OpenAI image API fallback, which sets both fields together via complete_job().

Source

Thrown at skills/hatch-pet/scripts/finalize_pet_run.py:154

        if job.get(flag)
    ]
    if blocked_flags:
        raise SystemExit(
            f"job {job_id} was marked as a local/synthetic row ({', '.join(blocked_flags)}); "
            "regenerate it with $imagegen"
        )

    if job.get("synthetic_test_source"):
        if not allow_synthetic_test_sources:
            raise SystemExit(
                f"job {job_id} uses a synthetic test source; rerun with real $imagegen output"
            )
        validate_hash(job, source=source, output=output, job_id=job_id)
        return

    if job.get("secondary_fallback"):
        if job.get("source_provenance") != "secondary-fallback-image-api":
            raise SystemExit(f"job {job_id} has invalid secondary fallback provenance")
        validate_hash(job, source=source, output=output, job_id=job_id)
        return

    if job.get("source_provenance") == "deterministic-mirror":
        validate_mirror_hash(job, source=source, output=output, job_id=job_id)
        return

    if job.get("source_provenance") != "built-in-imagegen":
        raise SystemExit(
            f"job {job_id} was not recorded as a built-in $imagegen output; "
            "use record_imagegen_result.py with the selected $CODEX_HOME/generated_images/.../ig_*.png file"
        )
    if is_relative_to(source, run_dir):
        raise SystemExit(
            f"job {job_id} source image is inside the pet run directory; "
            "do not use locally generated row artifacts as visual sources"
        )
    generated_root = default_generated_images_root()

View on GitHub (pinned to 5be4028344)

Solutions

  1. Re-run generate_pet_images.py for that job so complete_job() writes both secondary_fallback and source_provenance='secondary-fallback-image-api' atomically.
  2. Manually align the two fields in imagegen-jobs.json only if you understand the contract.
  3. Prefer regenerating with the real $imagegen built-in path (source_provenance='built-in-imagegen') to avoid the fallback entirely.

Example fix

// before (imagegen-jobs.json)
{"id":"waving","secondary_fallback":true,"source_provenance":"built-in-imagegen"}
// after
{"id":"waving","secondary_fallback":true,"source_provenance":"secondary-fallback-image-api"}
Defensive patterns

Strategy: validation

Validate before calling

if job.get('secondary_fallback') and job.get('source_provenance') != 'secondary-fallback-image-api':
    raise RuntimeError(f'job {job["id"]} secondary_fallback/provenance mismatch')

Prevention

When it happens

Trigger: job['secondary_fallback'] is truthy while job['source_provenance'] is something else (or missing). Caused by manually toggling secondary_fallback without updating provenance, or a partial write from complete_job().

Common situations: Editing imagegen-jobs.json to force a row through the fallback path; an interrupted generate_pet_images.py run that set secondary_fallback but did not yet set source_provenance.

Related errors


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