affaan-m/ECC · error · ContractError
has invalid
Error message
{label} has invalid {field} What it means
_validate_probe_evidence expects the probe's sample_times and scene_changes fields to be JSON lists. If either is missing-but-typed-wrong — a dict, string, or other non-list — the validator raises '<label> has invalid <field>'. Missing keys default to [] and are accepted.
Solutions
- Wrap the scalar value in a list in the probe document (e.g. [3.0]).
- Regenerate the probe with a matching tool version that emits arrays.
- If there are truly no events, omit the field or set it to [] rather than a scalar.
- Fix the probe-generation script's serialization to always output arrays for these fields.
Example fix
// before "scene_changes": 3.0 // after "scene_changes": [3.0]
Defensive patterns
Strategy: type-guard
Validate before calling
def probe_fields_are_lists(probe) -> bool:
return all(isinstance(probe.get(f, []), list)
for f in ('sample_times', 'scene_changes')) Type guard
def is_list_field(probe, field) -> bool:
return isinstance(probe, dict) and isinstance(probe.get(field, []), list) Try / catch
try:
validate_artifact_receipt(receipt)
except ContractError as e:
if 'has invalid sample_times' in str(e) or 'has invalid scene_changes' in str(e):
normalize_probe_lists(receipt['probe'])
else:
raise Prevention
- Always serialize sample_times/scene_changes as arrays, even with one element
- Use [] or omit the field entirely when there are no events
- Keep probe tool output schema stable across versions
- Type-check probe fields right after probe generation
When it happens
Trigger: validate_artifact_receipt where probe.sample_times or probe.scene_changes is a single number, a string, or a dict instead of an array; e.g. "scene_changes": 3 instead of [3.0].
Common situations: Probe tools that emit a single value when only one event occurs, hand-authored probes with scalar timestamps, JSON schema drift between probe tool versions.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- input_artifacts must be a list
- interview produced an invalid profile
- lacks probe evidence
- reference style evidence times must be finite and within…
- -32602
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/35789090c551983a.
Report an issue: GitHub.
Appendix: source
Thrown at skills/taste-application/scripts/tasteforge/contract.py:60
raise ContractError(f"{label} contains a non-finite numeric value")
elif isinstance(value, dict):
for nested in value.values():
_validate_numeric_evidence(nested, label=label)
elif isinstance(value, list):
for nested in value:
_validate_numeric_evidence(nested, label=label)
def _validate_probe_evidence(probe: Any, source_duration: float, *, label: str) -> None:
if not isinstance(probe, dict):
raise ContractError(f"{label} lacks probe evidence")
_validate_numeric_evidence(probe, label=label)
if probe.get("duration") != source_duration:
raise ContractError(f"{label} probe duration is not bound to source duration")
for field in ("sample_times", "scene_changes"):
values = probe.get(field, [])
if not isinstance(values, list):
raise ContractError(f"{label} has invalid {field}")
for value in values:
_validate_media_time(value, source_duration, label=f"{label} {field}")
samples = probe.get("style_samples", [])
if not isinstance(samples, list) or any(not isinstance(sample, dict) for sample in samples):
raise ContractError(f"{label} has invalid style evidence")
for sample in samples:
_validate_media_time(sample.get("time"), source_duration, label=f"{label} style evidence")
def _sha256(path: Path) -> str:
if not hasattr(os, "O_NOFOLLOW"):
raise ContractError("secure receipt validation requires O_NOFOLLOW")
descriptor = os.open(path, os.O_RDONLY | os.O_NOFOLLOW)
digest = hashlib.sha256()
try:
metadata = os.fstat(descriptor)
if not stat.S_ISREG(metadata.st_mode):
raise ContractError(f"receipt source is not a regular file: {path}")View on GitHub (pinned to 8321021c54)