affaan-m/ECC · error · ContractError
artifact lacks exact reference/time provenance
Error message
artifact {relative} lacks exact reference/time provenance What it means
validate_artifact_receipt requires every artifact receipt entry to carry a non-empty provenance list describing the exact source references and times the artifact was derived from. This error is raised when the 'provenance' key is absent, not a list, or an empty list. The library refuses to bless artifacts with no traceable origin.
Solutions
- Add a provenance list to the receipt entry with at least one object containing reference_path, reference_sha256, reference_times, and time_basis
- Regenerate the artifact through tasteforge so provenance is captured automatically
- If the artifact truly has no source, generate it as an original (unbound) rather than a reference-derived artifact, per the library's rules
- Cross-check the provenance against known_sources assembled by validate_bundle
Example fix
# before
receipt['artifacts']['clip.mp4'] = {'bytes': 1024, 'sha256': '...', 'modalities': ['video']}
# after
receipt['artifacts']['clip.mp4'] = {
'bytes': 1024, 'sha256': '...', 'modalities': ['video'],
'provenance': [{'reference_path': 'refs/intro.mp4',
'reference_sha256': 'a'*64,
'time_basis': 'whole_file', 'reference_times': []}]
} Defensive patterns
Strategy: validation
Validate before calling
p = receipt_entry.get('provenance')
assert isinstance(p, list) and len(p) > 0, 'receipt entry requires non-empty provenance list' Type guard
def has_provenance(entry: dict) -> bool:
p = entry.get('provenance')
return isinstance(p, list) and len(p) > 0 and all(isinstance(s, dict) for s in p) Try / catch
try:
validate_artifact_receipt(out_dir)
except ContractError as e:
if 'lacks exact reference/time provenance' in str(e):
rebuild_provenance_for_entry(entry_name)
else:
raise Prevention
- Generate receipts via the pipeline, never by hand
- Include a provenance template in receipt authoring tooling
- Run receipt schema linting before validate_bundle
- Keep provenance fields in one place to survive schema migrations
When it happens
Trigger: Validating a bundle whose receipt entry lacks 'provenance', has provenance set to null/{} / string, or has provenance: []. Also hit when hand-written receipts omit provenance entirely for an artifact that in fact derives from a reference.
Common situations: Manually authoring a receipt and forgetting provenance; a generation step that skips reference capture; older receipts from before provenance became required; deleting provenance to silence an unknown-source error without replacing it with valid sources.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- artifact has invalid reference path
- a generated candidate cannot claim original-source identity
- anchor evidence source duration is not bound to its receipt…
- artifact path must be a non-empty relative path
- artifact byte size does not match receipt
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/36329fb7fec046b8.
Report an issue: GitHub.
Appendix: source
Thrown at skills/taste-application/scripts/tasteforge/contract.py:408
try:
path.relative_to(out_dir)
except ValueError as error:
raise ContractError(f"artifact path escapes output directory: {relative}") from error
if entry.get("provider_execution") is not False:
raise ContractError(f"artifact {relative} permits provider execution")
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))View on GitHub (pinned to 8321021c54)