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 snapshot

View on GitHub (pinned to d540b00184)

Solutions

  1. Inspect the existing self.root/digest: if it is a prior valid snapshot, the harness invariant is violated - report it.
  2. Ensure the cache root is exclusive to one TaskAssetCache and empty on construction (mkdir uses exist_ok=False).
  3. 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

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


AI-assisted analysis of abhigyanpatwari/GitNexus@d540b00184 (2026-08-12). Data as JSON: /api/errors/21a422c8a9a6d8d8. Report an issue: GitHub.