{"record":{"id":"35789090c551983a","repo":"affaan-m/ECC","slug":"label-has-invalid-field","errorCode":null,"errorMessage":"{label} has invalid {field}","messagePattern":"(.+?) has invalid (.+?)","errorType":"validation","errorClass":"ContractError","httpStatus":null,"severity":"error","filePath":"skills/taste-application/scripts/tasteforge/contract.py","lineNumber":60,"sourceCode":"            raise ContractError(f\"{label} contains a non-finite numeric value\")\n    elif isinstance(value, dict):\n        for nested in value.values():\n            _validate_numeric_evidence(nested, label=label)\n    elif isinstance(value, list):\n        for nested in value:\n            _validate_numeric_evidence(nested, label=label)\n\n\ndef _validate_probe_evidence(probe: Any, source_duration: float, *, label: str) -> None:\n    if not isinstance(probe, dict):\n        raise ContractError(f\"{label} lacks probe evidence\")\n    _validate_numeric_evidence(probe, label=label)\n    if probe.get(\"duration\") != source_duration:\n        raise ContractError(f\"{label} probe duration is not bound to source duration\")\n    for field in (\"sample_times\", \"scene_changes\"):\n        values = probe.get(field, [])\n        if not isinstance(values, list):\n            raise ContractError(f\"{label} has invalid {field}\")\n        for value in values:\n            _validate_media_time(value, source_duration, label=f\"{label} {field}\")\n    samples = probe.get(\"style_samples\", [])\n    if not isinstance(samples, list) or any(not isinstance(sample, dict) for sample in samples):\n        raise ContractError(f\"{label} has invalid style evidence\")\n    for sample in samples:\n        _validate_media_time(sample.get(\"time\"), source_duration, label=f\"{label} style evidence\")\n\n\ndef _sha256(path: Path) -> str:\n    if not hasattr(os, \"O_NOFOLLOW\"):\n        raise ContractError(\"secure receipt validation requires O_NOFOLLOW\")\n    descriptor = os.open(path, os.O_RDONLY | os.O_NOFOLLOW)\n    digest = hashlib.sha256()\n    try:\n        metadata = os.fstat(descriptor)\n        if not stat.S_ISREG(metadata.st_mode):\n            raise ContractError(f\"receipt source is not a regular file: {path}\")","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/skills/taste-application/scripts/tasteforge/contract.py#L42-L78","documentation":"_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.","triggerScenarios":"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].","commonSituations":"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.","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."],"exampleFix":"// before\n\"scene_changes\": 3.0\n// after\n\"scene_changes\": [3.0]","handlingStrategy":"type-guard","validationCode":"def probe_fields_are_lists(probe) -> bool:\n    return all(isinstance(probe.get(f, []), list)\n               for f in ('sample_times', 'scene_changes'))","typeGuard":"def is_list_field(probe, field) -> bool:\n    return isinstance(probe, dict) and isinstance(probe.get(field, []), list)","tryCatchPattern":"try:\n    validate_artifact_receipt(receipt)\nexcept ContractError as e:\n    if 'has invalid sample_times' in str(e) or 'has invalid scene_changes' in str(e):\n        normalize_probe_lists(receipt['probe'])\n    else:\n        raise","preventionTips":["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"],"tags":["python","validation","schema"],"backgroundTag":"type-mismatch","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}