affaan-m/ECC · error · ValueError

reference source mutated while creating stable snapshot

Error message

reference source mutated while creating stable snapshot

What it means

After writing the snapshot, _stable_probe re-fstats the source descriptor and compares dev/ino/size/mtime_ns against the values captured before copying. Any difference means the file was modified while the snapshot was being created, so the digest would not describe one stable source object. It then re-hashes the descriptor and compares against the streamed digest as a second check, raising the same error on mismatch. This is the core TOCTOU protection of the 'stable probe' contract.

Solutions

  1. Rerun the workflow with nothing else writing the source file (stop watchers, formatters-on-save, codegen).
  2. Copy the source to a scratch location, freeze it, and probe the copy.
  3. If the file is legitimately rebuilt on save, exclude it from the probe target or pause the watcher for the run.
  4. If this fires deterministically with no concurrent writer, compare st_mtime_ns precision behavior of your filesystem and report the repro.

Example fix

// before (concurrent writer: dev server regenerates source)
python workflow.py probe src/generated.py  # fails

// after (freeze a copy first)
cp src/generated.py /tmp/frozen.py
python workflow.py probe /tmp/frozen.py
Defensive patterns

Strategy: fallback

Validate before calling

import hashlib, os
def file_fingerprint(path):
    st = os.stat(path)
    return (st.st_dev, st.st_ino, st.st_size, st.st_mtime_ns)

before = file_fingerprint(path)  # compare after run; retry if changed

Try / catch

import time
for attempt in range(3):
    try:
        return run_workflow(path, probe)
    except ValueError as e:
        if "mutated" in str(e) and attempt < 2:
            time.sleep(1)  # let the concurrent writer finish, then retry
            continue
        raise

Prevention

When it happens

Trigger: The source file is written, truncated, appended to, or replaced (size or mtime_ns change) between the pre-copy fstat and the post-copy fstat/re-hash; or the re-hashed digest of the fd differs from the digest accumulated during streaming.

Common situations: An editor auto-save or formatter (e.g. black, Prettier) touches the file during the probe; a build step or dev server regenerates the file concurrently; the file is rewritten via rename while an old inode is still being read; or filesystem timestamp granularity/storage shuffles metadata.

Understand the failure class

Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.

Related errors


AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16). Data as JSON: /api/errors/e25b383a15269102. Report an issue: GitHub.

Appendix: source

Thrown at skills/taste-application/scripts/tasteforge/workflow.py:97

                    if not chunk:
                        break
                    total += len(chunk)
                    digest.update(chunk)
                    view = memoryview(chunk)
                    while view:
                        written = os.write(snapshot_fd, view)
                        if written <= 0:
                            raise ValueError("stable source snapshot write made no progress")
                        view = view[written:]
                os.fsync(snapshot_fd)
            finally:
                os.close(snapshot_fd)
            source_digest = digest.hexdigest()
            copied = os.fstat(descriptor)
            if (before.st_dev, before.st_ino, before.st_size, before.st_mtime_ns) != (
                copied.st_dev, copied.st_ino, copied.st_size, copied.st_mtime_ns
            ):
                raise ValueError("reference source mutated while creating stable snapshot")
            verified_size, verified_digest = _hash_descriptor(descriptor)
            if verified_size != total or verified_digest != source_digest:
                raise ValueError("reference source mutated while creating stable snapshot")

            measured = probe(snapshot)

            after = os.fstat(descriptor)
            final_size, final_digest = _hash_descriptor(descriptor)
            if (before.st_dev, before.st_ino, before.st_size, before.st_mtime_ns) != (
                after.st_dev, after.st_ino, after.st_size, after.st_mtime_ns
            ) or final_size != total or final_digest != source_digest:
                raise ValueError("reference source mutated during media probing")
            rebound = os.open(path, os.O_RDONLY | os.O_NOFOLLOW)
            try:
                rebound_stat = os.fstat(rebound)
                if (rebound_stat.st_dev, rebound_stat.st_ino) != (before.st_dev, before.st_ino):
                    raise ValueError("reference source identity changed during media probing")
            finally:

View on GitHub (pinned to 8321021c54)