{"record":{"id":"a9b2aa921cc9c8d8","repo":"abhigyanpatwari/GitNexus","slug":"task-asset-snapshot-does-not-match-this-task-decla","errorCode":null,"errorMessage":"task asset snapshot does not match this task declaration","messagePattern":"task asset snapshot does not match this task declaration","errorType":"exception","errorClass":"SandboxError","httpStatus":null,"severity":"error","filePath":"eval/workflow_bench/task_assets.py","lineNumber":1075,"sourceCode":"def stage_task_assets(\n    task: Mapping[str, Any],\n    *,\n    repo: Path,\n    clone: Path,\n    snapshot: TaskAssetSnapshot | None = None,\n) -> list[ReadOnlyMount]:\n    \"\"\"Materialize copied assets and validate read-only dependency mounts.\n\n    ``snapshot`` is supplied by the benchmark runner so every arm reuses one\n    capture.  The optional path preserves the historic standalone helper API\n    for containment tests and external callers.\n    \"\"\"\n\n    repo_identity = _real_directory(repo, label=\"task asset repository\")\n    declarations, _ = _sandbox_copy_declarations(task)\n    if snapshot is not None:\n        if snapshot.repo_identity != repo_identity or snapshot.declarations != declarations:\n            raise SandboxError(\"task asset snapshot does not match this task declaration\")\n        snapshot.materialize(clone)\n        return _dependency_mounts(task, clone=clone, snapshot=snapshot)\n\n    if _sandbox_dependency_declarations(task):\n        raise SandboxError(\"sandbox_dependencies require a caller-owned immutable task asset snapshot\")\n\n    with tempfile.TemporaryDirectory(prefix=\"wfbench-asset-snapshot-\") as temporary:\n        with TaskAssetCache(Path(temporary) / \"cache\") as cache:\n            ephemeral = cache.prepare(task, repo=repo_identity, resolved_sha=\"unbound\")\n            ephemeral.materialize(clone)\n    return []\n","sourceCodeStart":1057,"sourceCodeEnd":1087,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/d540b00184d71a896261ee02670da9a92d59d8f7/eval/workflow_bench/task_assets.py#L1057-L1087","documentation":"Raised by stage_task_assets when a supplied snapshot's repo_identity (real directory path of the repo) or sandbox_copy declarations do not match the current task/repo. The snapshot is provenance-bound: it must have been captured from the same real repo directory and the same sandbox_copy declaration set, otherwise its frozen bytes cannot be trusted to represent this task's inputs.","triggerScenarios":"Passing a snapshot built from repo A into a stage call for repo B; reusing a snapshot after the sandbox_copy declaration was edited; passing a snapshot whose repo_identity was resolved via a symlink while stage resolves a different real path (or vice versa); snapshot built with resolved_sha='unbound' for a task that now needs a bound snapshot.","commonSituations":"Caching a snapshot across CI runs and reusing it after the repo path changed (different workdir); editing sandbox_copy between prepare and stage; resolving repo via a symlink in one path and the realpath in another; mixing the ephemeral standalone snapshot path with the benchmark runner's caller-owned snapshot.","solutions":["Build the snapshot and stage from it in the same run, passing the identical repo Path to both cache.prepare and stage_task_assets (resolve symlinks consistently — _real_directory is used both sides).","After editing sandbox_copy in a task, call cache.prepare again to capture a fresh snapshot; do not reuse the old one.","Key any snapshot cache by (repo_identity, resolved_sha, sandbox_copy declarations, sandbox_dependencies) and discard entries that no longer match."],"exampleFix":"# before: snapshot built once, reused after sandbox_copy changed\nsnapshot = cache.prepare(task, repo=repo, resolved_sha=sha)\ntask['sandbox_copy'].append('build/out')     # declaration mutated\nstage_task_assets(task, repo=repo, clone=clone, snapshot=snapshot)  # -> mismatch\n\n# after: rebuild the snapshot whenever the task declaration changes\ntask['sandbox_copy'].append('build/out')\nsnapshot = cache.prepare(task, repo=repo, resolved_sha=sha)\nstage_task_assets(task, repo=repo, clone=clone, snapshot=snapshot)","handlingStrategy":"validation","validationCode":"from .task_assets import _sandbox_copy_declarations, _real_directory\n\ndef assert_snapshot_matches_task(task, *, repo, snapshot) -> None:\n    repo_identity = _real_directory(repo, label='task asset repository')\n    declarations, _ = _sandbox_copy_declarations(task)\n    if snapshot.repo_identity != repo_identity or snapshot.declarations != declarations:\n        raise ValueError(\n            'snapshot provenance does not match task/repo; rebuild via cache.prepare.'\n        )\n\n# Call before stage_task_assets; rebuild if mismatched.","typeGuard":"def snapshot_matches_task(task, *, repo, snapshot) -> bool:\n    repo_identity = _real_directory(repo, label='task asset repository')\n    declarations, _ = _sandbox_copy_declarations(task)\n    return snapshot.repo_identity == repo_identity and snapshot.declarations == declarations","tryCatchPattern":"from .proposer_sandbox import SandboxError\n\ntry:\n    stage_task_assets(task, repo=repo, clone=clone, snapshot=snapshot)\nexcept SandboxError as exc:\n    if 'does not match this task declaration' in str(exc):\n        with TaskAssetCache(cache_dir) as cache:\n            snapshot = cache.prepare(task, repo=_real_directory(repo, label='task asset repository'), resolved_sha=sha)\n        stage_task_assets(task, repo=repo, clone=clone, snapshot=snapshot)\n    else:\n        raise","preventionTips":["Resolve repo consistently (same real path) for both cache.prepare and stage_task_assets.","Rebuild the snapshot whenever sandbox_copy or the repo workdir changes.","Key snapshot caches by (repo_identity, resolved_sha, sandbox_copy declarations, sandbox_dependencies)."],"tags":["snapshot","validation","integrity","sandbox"],"backgroundTag":null,"analyzedSha":"d540b00184d71a896261ee02670da9a92d59d8f7","analyzedAt":"2026-08-12T19:50:25.132Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}