abhigyanpatwari/GitNexus · error · SandboxError
task asset snapshot key collision: {digest}
Error message
task asset snapshot key collision: {digest} What it means
After computing the snapshot digest and atomically building into a temp dir, the destination self.root/digest already exists. The _by_definition memo already returns identical definitions, so reaching this branch means either a genuine SHA-256 collision (astronomically unlikely) or a stray directory left in the cache root.
Source
Thrown at eval/workflow_bench/task_assets.py:323
dependencies = tuple(dependency_snapshots)
dependency_content_digest, dependency_manifest_digest = _dependency_digests(dependencies)
if expected_dependency_binding is not None:
_validate_dependency_binding_values(
expected_dependency_binding,
content_digest=dependency_content_digest,
manifest_digest=dependency_manifest_digest,
)
digest = _snapshot_digest(
repo_identity=repo_identity,
resolved_sha=resolved_sha,
declarations=declarations,
manifest_digest=manifest_digest,
dependency_content_digest=dependency_content_digest,
dependency_manifest_digest=dependency_manifest_digest,
)
destination = self.root / digest
if destination.exists():
raise SandboxError(f"task asset snapshot key collision: {digest}")
os.replace(building, destination)
_freeze_snapshot(destination)
snapshot = TaskAssetSnapshot(
root=destination,
digest=digest,
manifest_digest=manifest_digest,
repo_identity=repo_identity,
resolved_sha=resolved_sha,
declarations=declarations,
entries=entries,
dependency_declarations=dependency_identity,
dependencies=dependencies,
dependency_content_digest=dependency_content_digest,
dependency_manifest_digest=dependency_manifest_digest,
total_bytes=budget.total_bytes,
)
self._by_definition[definition] = snapshot
return snapshotView on GitHub (pinned to d540b00184)
Solutions
- Inspect the existing self.root/digest: if it is a prior valid snapshot, the harness invariant is violated - report it.
- Ensure the cache root is exclusive to one TaskAssetCache and empty on construction (mkdir uses exist_ok=False).
- Verify _snapshot_digest inputs are complete (no truncation) and that schema_version is bumped whenever digest inputs change.
Defensive patterns
Strategy: try-catch
Validate before calling
import os
def assert_cache_root_unused(root):
if os.path.exists(root) and any(os.scandir(root)):
raise RuntimeError(f"cache root not empty: {root}") Try / catch
from workflow_bench.proposer_sandbox import SandboxError
try:
snapshot = cache.prepare(task, repo=repo, resolved_sha=sha)
except SandboxError as exc:
if "snapshot key collision" in str(exc):
log.error("digest collision or stray cache entry - investigate %s", exc)
raise Prevention
- Give each TaskAssetCache an exclusive, empty root (mkdir exist_ok=False already enforces this).
- Bump _snapshot_digest schema_version whenever digest inputs change.
- Never manually drop directories into the cache root.
When it happens
Trigger: Two distinct (repo, sha, declarations, dependencies) tuples hash to the same digest, or a previous run/leak left a directory at that exact digest path before os.replace.
Common situations: The cache root was pre-populated or shared with another process; a prior run crashed leaving state and a manual copy was dropped in; _snapshot_digest regressed to truncate its inputs.
Related errors
- transcript artifact size does not match its results row: {pa
- transcript artifact digest does not match its results row: {
- plan artifact changed while opening: {path}
- plan artifact changed while hashing: {path}
- planning deleted existing plan artifact(s): {deleted}
AI-assisted analysis of abhigyanpatwari/GitNexus@d540b00184 (2026-08-12).
Data as JSON: /api/errors/21a422c8a9a6d8d8.
Report an issue: GitHub.