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

  1. Wrap the scalar value in a list in the probe document (e.g. [3.0]).
  2. Regenerate the probe with a matching tool version that emits arrays.
  3. If there are truly no events, omit the field or set it to [] rather than a scalar.
  4. 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

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


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)