nexu-io/open-design · error · SystemExit

running-left mirror source hash does not match imagegen-jobs

Error message

running-left mirror source hash does not match imagegen-jobs.json

What it means

Raised by validate_mirror_hash when the SHA-256 of the on-disk running-right.png (source) does not equal job['source_sha256'] recorded in imagegen-jobs.json. This detects post-generation mutation of the source strip that the mirror is supposed to derive from.

Source

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

            "use derive_running_left_from_running_right.py after visual review"
        )

    expected_source_hash = job.get("source_sha256")
    expected_output_hash = job.get("output_sha256")
    if not isinstance(expected_source_hash, str) or not expected_source_hash:
        raise SystemExit("running-left mirror job is missing source_sha256")
    if not isinstance(expected_output_hash, str) or not expected_output_hash:
        raise SystemExit("running-left mirror job is missing output_sha256")
    if not source.is_file():
        raise SystemExit(f"running-left mirror source image no longer exists: {source}")
    if not output.is_file():
        raise SystemExit(f"running-left mirrored output is missing: {output}")
    if source.name != "running-right.png" or source.parent.name != "decoded":
        raise SystemExit("running-left mirror source must be decoded/running-right.png")
    if output.name != "running-left.png" or output.parent.name != "decoded":
        raise SystemExit("running-left mirror output must be decoded/running-left.png")
    if file_sha256(source) != expected_source_hash:
        raise SystemExit("running-left mirror source hash does not match imagegen-jobs.json")
    if file_sha256(output) != expected_output_hash:
        raise SystemExit(
            "running-left mirrored output hash does not match imagegen-jobs.json; "
            "rerun derive_running_left_from_running_right.py"
        )
    with Image.open(source) as source_image, Image.open(output) as output_image:
        expected = ImageOps.mirror(source_image.convert("RGBA"))
        actual = output_image.convert("RGBA")
        if expected.size != actual.size or expected.tobytes() != actual.tobytes():
            raise SystemExit(
                "running-left mirrored output is not an exact horizontal mirror of running-right"
            )


def validate_completed_job_source(
    job: dict[str, object],
    *,
    run_dir: Path,

View on GitHub (pinned to 5be4028344)

Solutions

  1. Re-generate decoded/running-right.png via the real $imagegen flow so its hash matches the recorded source_sha256.
  2. If running-right.png was intentionally refreshed, re-derive running-left with derive_running_left_from_running_right.py so both source_sha256 and output_sha256 are recomputed.
  3. Audit git/file mtimes to find what modified decoded/running-right.png after ingest.
Defensive patterns

Strategy: validation

Validate before calling

import hashlib
def sha256(p):
    h = hashlib.sha256()
    with open(p, 'rb') as f:
        for chunk in iter(lambda: f.read(1<<20), b''):
            h.update(chunk)
    return h.hexdigest()
if sha256(source) != job['source_sha256']:
    raise RuntimeError('running-right.png changed since mirror job was recorded')

Prevention

When it happens

Trigger: file_sha256(source) != job['source_sha256'] for the running-left mirror job. Occurs if running-right.png was re-encoded, re-saved, or overwritten after the mirror job's hashes were recorded.

Common situations: Re-running the running-right imagegen job without updating the running-left mirror job's source_sha256; image editor that re-compressed the PNG; copying a different file over decoded/running-right.png.

Related errors


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