{"record":{"id":"25764b44d6ce4673","repo":"affaan-m/ECC","slug":"receipt-source-is-unavailable-source-path","errorCode":null,"errorMessage":"receipt source is unavailable: {source_path}","messagePattern":"receipt source is unavailable: (.+?)","errorType":"validation","errorClass":"ContractError","httpStatus":null,"severity":"error","filePath":"skills/taste-application/scripts/tasteforge/contract.py","lineNumber":351,"sourceCode":"                if not _is_finite_real(source_duration):\n                    raise ContractError(\"receipt reference has an invalid finite source duration\")\n                source_duration = cast(float, source_duration)\n                if float(source_duration) <= 0:\n                    raise ContractError(\"receipt reference has an invalid finite source duration\")\n                source_durations[(source_path, expected_digest)] = float(source_duration)\n                _validate_probe_evidence(\n                    source.get(\"probe\"), float(source_duration), label=\"receipt reference\"\n                )\n    source_policy = receipt.get(\"source_availability_policy\")\n    if known_sources and source_policy not in {\"allow_unavailable\", \"require_available\"}:\n        raise ContractError(\"receipt must declare an explicit source availability policy\")\n    for source_path, expected_digest in sorted(known_sources):\n        path = Path(source_path)\n        try:\n            metadata = path.lstat()\n        except FileNotFoundError:\n            if source_policy == \"require_available\":\n                raise ContractError(f\"receipt source is unavailable: {source_path}\") from None\n            continue\n        if stat.S_ISLNK(metadata.st_mode) or not stat.S_ISREG(metadata.st_mode):\n            raise ContractError(f\"receipt source is not a safe regular file: {source_path}\")\n        try:\n            actual_digest = _sha256(path)\n        except FileNotFoundError:\n            if source_policy == \"require_available\":\n                raise ContractError(f\"receipt source is unavailable: {source_path}\") from None\n            continue\n        except OSError:\n            raise ContractError(f\"receipt source cannot be securely read: {source_path}\") from None\n        if actual_digest != expected_digest:\n            raise ContractError(f\"receipt source SHA-256 changed after generation: {source_path}\")\n\n    emitted = {\n        path.relative_to(out_dir).as_posix()\n        for path in out_dir.rglob(\"*\")\n        if path.is_file() and path.name != \"receipt.json\"","sourceCodeStart":333,"sourceCodeEnd":369,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/skills/taste-application/scripts/tasteforge/contract.py#L333-L369","documentation":"With \"source_availability_policy\": \"require_available\", every declared receipt source must exist on disk at validation time. If Path(source_path).lstat() raises FileNotFoundError and the policy is require_available, ContractError('receipt source is unavailable: <path>') is raised. Under allow_unavailable, missing files are silently skipped instead.","triggerScenarios":"validate_artifact_receipt/validate_bundle run in a working directory where a declared source file was deleted, renamed, or never checked out; running validation from the wrong cwd so relative paths don't resolve; CI checkouts that exclude large evidence files (LFS not pulled).","commonSituations":"Running the validator from a different directory than generation; files cleaned by `git clean`; Git LFS/GitLab sparse checkout skipping evidence assets; sources outside the repo on a machine that lacks them; case-sensitive filesystems where the path casing differs.","solutions":["Restore the missing source file at the declared path (git checkout / re-download / pull LFS objects)","Run validation from the same working directory used at generation so relative paths resolve","Switch the receipt to \"allow_unavailable\" only if missing sources are genuinely acceptable","Regenerate the receipt if the source set changed"],"exampleFix":"# before (from wrong cwd)\ncd /tmp && python -m tasteforge validate bundle.tzst\n# after\ncd /path/to/project && python -m tasteforge validate bundle.tzst","handlingStrategy":"validation","validationCode":"from pathlib import Path\n\ndef sources_present(receipt, base='.'):\n    paths = [s['path'] for s in receipt.get('references', []) + receipt.get('evidence_files', [])]\n    missing = [p for p in paths if not (Path(base) / p).exists()]\n    return missing  # empty list means OK","typeGuard":null,"tryCatchPattern":"try:\n    validate_artifact_receipt(receipt, out_dir)\nexcept ContractError as e:\n    if str(e).startswith('receipt source is unavailable'):\n        missing = str(e).rsplit(': ', 1)[1]\n        # restore file, fix cwd, or switch policy before retrying\n    raise","preventionTips":["Run validation from the same cwd used at generation time","Commit or archive all declared sources alongside the receipt","Pull LFS objects / full checkouts in CI before validating","Pre-check all source paths exist before invoking validation"],"tags":["filesystem","receipt","missing-file"],"backgroundTag":"file-not-found","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"}