{"record":{"id":"bf9c37e3fb764dba","repo":"abhigyanpatwari/GitNexus","slug":"task-asset-snapshot-file-changed-entry-path","errorCode":null,"errorMessage":"task asset snapshot file changed: {entry.path}","messagePattern":"task asset snapshot file changed: (.+?)","errorType":"exception","errorClass":"SandboxError","httpStatus":null,"severity":"critical","filePath":"eval/workflow_bench/task_assets.py","lineNumber":809,"sourceCode":"            relative.name,\n            src_dir_fd=source_parent,\n            dst_dir_fd=destination_parent,\n        )\n    finally:\n        os.close(destination_parent)\n        os.close(source_parent)\n\n\ndef _materialize_file(\n    source: Path,\n    destination: Path,\n    entry: AssetManifestEntry,\n    *,\n    fallback_budget: int,\n) -> int:\n    metadata = source.lstat()\n    if stat.S_ISLNK(metadata.st_mode) or not stat.S_ISREG(metadata.st_mode) or metadata.st_size != entry.size:\n        raise SandboxError(f\"task asset snapshot file changed: {entry.path}\")\n    temporary = destination.with_name(f\".{destination.name}.{uuid.uuid4().hex}.tmp\")\n    source_descriptor = os.open(source, os.O_RDONLY | getattr(os, \"O_CLOEXEC\", 0) | getattr(os, \"O_NOFOLLOW\", 0))\n    destination_descriptor = os.open(\n        temporary,\n        os.O_WRONLY | os.O_CREAT | os.O_EXCL | getattr(os, \"O_CLOEXEC\", 0),\n        0o600,\n    )\n    fallback_bytes = 0\n    try:\n        opened = os.fstat(source_descriptor)\n        if _mutation_identity(opened) != _mutation_identity(metadata):\n            raise SandboxError(f\"task asset snapshot file changed: {entry.path}\")\n        if _try_reflink(source_descriptor, destination_descriptor):\n            if os.fstat(destination_descriptor).st_size != entry.size:\n                raise SandboxError(f\"task asset reflink produced an invalid file: {entry.path}\")\n        else:\n            if entry.size > fallback_budget:\n                raise SandboxError(","sourceCodeStart":791,"sourceCodeEnd":827,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/d540b00184d71a896261ee02670da9a92d59d8f7/eval/workflow_bench/task_assets.py#L791-L827","documentation":"_materialize_file first lstat's the source snapshot file and requires: not a symlink, is a regular file, and st_size equals entry.size from the manifest. Any deviation aborts — the snapshot must be byte-identical to what was captured. Indicates the captured snapshot file was replaced, truncated, extended, or symlinked between capture and materialize, or that entry.size in the manifest is stale.","triggerScenarios":"The captured snapshot file was mutated after capture; the manifest size field does not match the on-disk file; the snapshot root was replaced or corrupted.","commonSituations":"Two arms sharing the snapshot root with one mutating it (the snapshot is meant to be immutable); disk corruption; an external process (backup, AV) touching the cache dir.","solutions":["Confirm nothing writes to the TaskAssetCache.root directory during or between runs","Delete the cache entry and re-prepare the snapshot from scratch","Verify entry.size matches os.lstat(source).st_size to detect a stale manifest"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"import os, stat\nfrom pathlib import Path\n\ndef snapshot_files_match_manifest(snapshot_root: Path, entries) -> list[str]:\n    bad = []\n    root = snapshot_root / \"sandbox-copy\"\n    for e in entries:\n        if e.get(\"kind\") != \"file\":\n            continue\n        p = root / Path(*PurePosixPath(e[\"path\"]).parts)\n        try:\n            m = p.lstat()\n        except OSError as exc:\n            bad.append(f\"{e['path']}: {exc}\"); continue\n        if stat.S_ISLNK(m.st_mode) or not stat.S_ISREG(m.st_mode) or m.st_size != e[\"size\"]:\n            bad.append(e[\"path\"])\n    return bad","typeGuard":null,"tryCatchPattern":"from eval.workflow_bench.proposer_sandbox import SandboxError\n\ntry:\n    snapshot.materialize(clone)\nexcept SandboxError as exc:\n    if \"snapshot file changed\" in str(exc):\n        raise SystemExit(f\"snapshot mutated since capture; delete the cache entry and re-prepare: {exc}\") from exc\n    raise","preventionTips":["Treat the TaskAssetCache.root as immutable once written; never let a second writer touch it","Disable backup and AV scanners on the cache directory","Validate snapshot files against the manifest size before materialize"],"tags":["sandbox","snapshot","integrity","toctou"],"backgroundTag":null,"analyzedSha":"d540b00184d71a896261ee02670da9a92d59d8f7","analyzedAt":"2026-08-12T19:50:25.132Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}