affaan-m/ECC · error · ContractError
rule lacks time evidence
Error message
rule {rule.get('rule_id')} lacks time evidence What it means
Each evidence item must carry a non-empty 'times' list of media timestamps so rules are anchored in time within the source. Missing, non-list, or empty 'times' raises this ContractError, and each time is further validated against 'source_duration'.
Solutions
- Add a non-empty 'times' list of finite numbers to each evidence item.
- Ensure each time value is finite (no NaN/inf) and within [0, source_duration].
- Set a valid 'source_duration' on the evidence item if it is missing, since times are validated against it.
- Fix the upstream timestamp extractor to emit at least one time per evidence item before building provenance.
Example fix
// before
item = {"reference_sha256": digest, "source_duration": 10.0, "times": []}
// after
item = {"reference_sha256": digest, "source_duration": 10.0, "times": [0.5, 2.25]} Defensive patterns
Strategy: validation
Validate before calling
import math
def times_ok(item):
times, dur = item.get("times"), item.get("source_duration")
return (isinstance(times, list) and len(times) > 0
and all(isinstance(t, (int, float)) and math.isfinite(t) for t in times)
and isinstance(dur, (int, float)) and all(0 <= t <= dur for t in times)) Type guard
def evidence_is_time_anchored(item: dict) -> bool:
import math
t = item.get("times")
return isinstance(t, list) and len(t) > 0 and all(
isinstance(x, (int, float)) and math.isfinite(x) for x in t) Try / catch
try:
validate_provenance(payload)
except ContractError as e:
if "lacks time evidence" in str(e):
payload = reextract_timestamps(payload)
validate_provenance(payload)
else:
raise Prevention
- Require the timestamp extractor to emit at least one time per evidence item.
- Clamp/validate times against source_duration at extraction time, not validation time.
- Guard frame-rate divisions against zero to avoid NaN/inf times.
- Keep times per evidence item, not at the rule level.
When it happens
Trigger: Evidence item like {'reference_sha256': '<64-hex>'} with no 'times', times = None, or times = []; also times containing non-finite or out-of-duration values that fail _validate_media_time.
Common situations: Evidence recorded from a detector that produced no timestamps; a schema migration dropping the times field; timestamps accidentally placed at the rule level instead of per evidence item; NaN/inf times from float division by zero frame rate.
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
- probe duration is not bound to source duration
- a generated candidate cannot claim original-source identity
- anchor evidence source duration is not bound to its receipt…
- apply_local needs at least one media clip
- artifact cites an unknown provenance source
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/ee8f65a176dee368.
Report an issue: GitHub.
Appendix: source
Thrown at skills/taste-application/scripts/tasteforge/contract.py:273
raise ContractError(f"effect {event.get('effect')} lacks placement constraints")
def validate_provenance(payload: dict[str, Any]) -> None:
"""Require every declared rule to cite immutable, timestamped evidence."""
rules = payload.get("rules")
if not isinstance(rules, list) or not rules:
raise ContractError("provenance must contain derived rules")
for rule in rules:
evidence = rule.get("evidence")
if not isinstance(evidence, list) or not evidence:
raise ContractError(f"rule {rule.get('rule_id')} lacks reference evidence")
for item in evidence:
digest = item.get("reference_sha256")
if not isinstance(digest, str) or len(digest) != 64:
raise ContractError(f"rule {rule.get('rule_id')} lacks immutable reference evidence")
times = item.get("times")
if not isinstance(times, list) or not times:
raise ContractError(f"rule {rule.get('rule_id')} lacks time evidence")
source_duration = item.get("source_duration")
for time in times:
_validate_media_time(
time, source_duration, label=f"rule {rule.get('rule_id')} time evidence"
)
def validate_manifests(manifests_dir: str | Path) -> None:
"""Require image, video, and 3D-asset dry-run request manifests."""
manifests_dir = Path(manifests_dir)
found = {path.stem for path in manifests_dir.glob("*.json")} if manifests_dir.is_dir() else set()
missing = _REQUIRED_MODALITIES - found
if missing:
raise ContractError(f"missing modality manifests: {sorted(missing)}")
for modality in _REQUIRED_MODALITIES:
payload = json.loads((manifests_dir / f"{modality}.json").read_text(encoding="utf-8"))
if payload.get("modality") != modality or not payload.get("requests"):
raise ContractError(f"invalid or empty {modality} manifest")View on GitHub (pinned to 8321021c54)