affaan-m/ECC · error · ContractError

artifact has invalid reference SHA-256

Error message

artifact {relative} has invalid reference SHA-256

What it means

Each provenance source must include a 'reference_sha256' that is a string of exactly 64 hex characters (a SHA-256 digest). This error is raised when the digest is missing, non-string, or the wrong length. It lets the validator match the cited source against the set of known reference files.

Solutions

  1. Recompute the reference file digest with hashlib.sha256(...).hexdigest() and store the full 64-char string
  2. Verify no truncation or surrounding whitespace/prefix when pasting the hash
  3. Regenerate the receipt through tasteforge so digests are computed correctly
  4. Ensure the reference file itself still hashes to the recorded digest before validation

Example fix

import hashlib
# before
'reference_sha256': '3f2a1b'  # truncated
# after
'reference_sha256': hashlib.sha256(Path('refs/intro.mp4').read_bytes()).hexdigest()
Defensive patterns

Strategy: validation

Validate before calling

import re
d = src.get('reference_sha256')
assert isinstance(d, str) and re.fullmatch(r'[0-9a-f]{64}', d), f'bad digest: {d!r}'

Type guard

def valid_sha256(value) -> bool:
    return isinstance(value, str) and len(value) == 64 and all(c in '0123456789abcdef' for c in value)

Try / catch

try:
    validate_artifact_receipt(out_dir)
except ContractError as e:
    if 'invalid reference SHA-256' in str(e):
        recompute_reference_digests(receipt)
    else:
        raise

Prevention

When it happens

Trigger: A provenance source whose reference_sha256 is absent, truncated (e.g. short hash), a full hash with 0x prefix, a non-string type, or computed with a different algorithm (MD5/SHA-1) producing the wrong length.

Common situations: Hand-editing receipts with abbreviated hashes; hashing with md5() instead of sha256(); copying hashes from other tooling formats; older receipts generated before 64-char digests were enforced.

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/19710a89627c53f3. Report an issue: GitHub.

Appendix: source

Thrown at skills/taste-application/scripts/tasteforge/contract.py:414

        if not isinstance(entry.get("genre_numbers"), list):
            raise ContractError(f"artifact {relative} lacks genre binding")
        modalities = entry.get("modalities")
        if (not isinstance(modalities, list)
                or any(modality not in _REQUIRED_MODALITIES for modality in modalities)):
            raise ContractError(f"artifact {relative} has invalid modality binding")
        if entry.get("bytes") != path.stat().st_size:
            raise ContractError(f"artifact {relative} byte size does not match receipt")
        if entry.get("sha256") != _sha256(path):
            raise ContractError(f"artifact {relative} SHA-256 does not match receipt")
        provenance = entry.get("provenance")
        if not isinstance(provenance, list) or not provenance:
            raise ContractError(f"artifact {relative} lacks exact reference/time provenance")
        for source in provenance:
            if not isinstance(source.get("reference_path"), str) or not source["reference_path"]:
                raise ContractError(f"artifact {relative} has invalid reference path")
            digest = source.get("reference_sha256")
            if not isinstance(digest, str) or len(digest) != 64:
                raise ContractError(f"artifact {relative} has invalid reference SHA-256")
            if (source["reference_path"], digest) not in known_sources:
                raise ContractError(f"artifact {relative} cites an unknown provenance source")
            times = source.get("reference_times")
            basis = source.get("time_basis")
            if not isinstance(times, list) or basis not in {"media_seconds", "whole_file"}:
                raise ContractError(f"artifact {relative} has invalid reference/time provenance")
            if basis == "media_seconds" and not times:
                raise ContractError(f"artifact {relative} lacks media reference times")
            if basis == "whole_file" and times:
                raise ContractError(f"artifact {relative} whole-file provenance must not invent times")
            if basis == "media_seconds":
                expected_duration = source_durations.get((source["reference_path"], digest))
                if expected_duration is None or source.get("source_duration") != expected_duration:
                    raise ContractError(f"artifact {relative} has an unbound source duration")
                for time in times:
                    _validate_media_time(
                        time, expected_duration,
                        label=f"artifact {relative} media reference time",

View on GitHub (pinned to 8321021c54)