{"record":{"id":"f4e404dadf00c4fb","repo":"affaan-m/ECC","slug":"artifact-relative-has-invalid-reference-path","errorCode":null,"errorMessage":"artifact {relative} has invalid reference path","messagePattern":"artifact (.+?) has invalid reference path","errorType":"validation","errorClass":"ContractError","httpStatus":null,"severity":"error","filePath":"skills/taste-application/scripts/tasteforge/contract.py","lineNumber":411,"sourceCode":"            raise ContractError(f\"artifact path escapes output directory: {relative}\") from error\n        if entry.get(\"provider_execution\") is not False:\n            raise ContractError(f\"artifact {relative} permits provider execution\")\n        if not isinstance(entry.get(\"genre_numbers\"), list):\n            raise ContractError(f\"artifact {relative} lacks genre binding\")\n        modalities = entry.get(\"modalities\")\n        if (not isinstance(modalities, list)\n                or any(modality not in _REQUIRED_MODALITIES for modality in modalities)):\n            raise ContractError(f\"artifact {relative} has invalid modality binding\")\n        if entry.get(\"bytes\") != path.stat().st_size:\n            raise ContractError(f\"artifact {relative} byte size does not match receipt\")\n        if entry.get(\"sha256\") != _sha256(path):\n            raise ContractError(f\"artifact {relative} SHA-256 does not match receipt\")\n        provenance = entry.get(\"provenance\")\n        if not isinstance(provenance, list) or not provenance:\n            raise ContractError(f\"artifact {relative} lacks exact reference/time provenance\")\n        for source in provenance:\n            if not isinstance(source.get(\"reference_path\"), str) or not source[\"reference_path\"]:\n                raise ContractError(f\"artifact {relative} has invalid reference path\")\n            digest = source.get(\"reference_sha256\")\n            if not isinstance(digest, str) or len(digest) != 64:\n                raise ContractError(f\"artifact {relative} has invalid reference SHA-256\")\n            if (source[\"reference_path\"], digest) not in known_sources:\n                raise ContractError(f\"artifact {relative} cites an unknown provenance source\")\n            times = source.get(\"reference_times\")\n            basis = source.get(\"time_basis\")\n            if not isinstance(times, list) or basis not in {\"media_seconds\", \"whole_file\"}:\n                raise ContractError(f\"artifact {relative} has invalid reference/time provenance\")\n            if basis == \"media_seconds\" and not times:\n                raise ContractError(f\"artifact {relative} lacks media reference times\")\n            if basis == \"whole_file\" and times:\n                raise ContractError(f\"artifact {relative} whole-file provenance must not invent times\")\n            if basis == \"media_seconds\":\n                expected_duration = source_durations.get((source[\"reference_path\"], digest))\n                if expected_duration is None or source.get(\"source_duration\") != expected_duration:\n                    raise ContractError(f\"artifact {relative} has an unbound source duration\")\n                for time in times:","sourceCodeStart":393,"sourceCodeEnd":429,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/skills/taste-application/scripts/tasteforge/contract.py#L393-L429","documentation":"Each provenance source inside a receipt entry must have a 'reference_path' that is a non-empty string. This error is raised when reference_path is missing, null, not a string, or an empty string. It ensures every cited source points to an identifiable reference file.","triggerScenarios":"validate_artifact_receipt iterating a provenance list and finding a source dict without a valid reference_path — e.g. hand-edited receipt, a generator emitting reference_path: None, or a typo'd key like referencePaths.","commonSituations":"Manual receipt authoring with key-name typos, JSON tools serializing empty strings, scripts that substitute None when a reference path variable is unset, migrating receipts between schema versions.","solutions":["Set reference_path to the non-empty relative path of the actual reference file for that source","Fix key-name typos so the field is exactly 'reference_path'","Regenerate the receipt via the tasteforge pipeline to produce well-formed provenance","Ensure the JSON serialization step is not converting empty paths to ''"],"exampleFix":"# before\n{'reference_sha256': 'a'*64, 'time_basis': 'whole_file'}\n# after\n{'reference_path': 'refs/intro.mp4', 'reference_sha256': 'a'*64, 'time_basis': 'whole_file'}","handlingStrategy":"validation","validationCode":"for src in entry.get('provenance', []):\n    rp = src.get('reference_path')\n    assert isinstance(rp, str) and rp, f'invalid reference_path: {rp!r}'","typeGuard":"def valid_reference_path(src: dict) -> bool:\n    rp = src.get('reference_path')\n    return isinstance(rp, str) and len(rp) > 0","tryCatchPattern":"try:\n    validate_artifact_receipt(out_dir)\nexcept ContractError as e:\n    if 'invalid reference path' in str(e):\n        fix_or_regenerate_receipt()\n    else:\n        raise","preventionTips":["Use exact field name 'reference_path' via a shared schema/dataclass","Validate receipt JSON against a JSON Schema before submission","Avoid manual JSON editing; use helper scripts that guarantee field presence","Watch for serializers coercing None to ''"],"tags":["provenance","validation","receipt"],"backgroundTag":"invalid-argument-format","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"}