abhigyanpatwari/GitNexus · error · SandboxError
task asset cache is already closed
Error message
task asset cache is already closed
What it means
TaskAssetCache.prepare refuses to run after close() (or context-manager __exit__). The cache root has been deleted, so any new snapshot would be written into a removed tree.
Source
Thrown at eval/workflow_bench/task_assets.py:216
def __enter__(self) -> TaskAssetCache:
return self
def __exit__(self, _exc_type: object, _exc: object, _traceback: object) -> None:
self.close()
def prepare(
self,
task: Mapping[str, Any],
*,
repo: Path,
resolved_sha: str,
expected_dependency_binding: Mapping[str, Any] | None = None,
) -> TaskAssetSnapshot:
"""Capture or reuse all copied and mounted task bytes in one snapshot."""
if self._closed:
raise SandboxError("task asset cache is already closed")
repo_identity = _real_directory(repo, label="task asset repository")
declarations, relative_paths = _sandbox_copy_declarations(task)
dependency_declarations = _sandbox_dependency_declarations(task)
dependency_identity = tuple((declaration.source, declaration.target) for declaration in dependency_declarations)
definition = (str(repo_identity), resolved_sha, declarations, dependency_identity)
existing = self._by_definition.get(definition)
if existing is not None:
if expected_dependency_binding is not None:
existing.validate_dependency_binding(expected_dependency_binding)
return existing
building = Path(tempfile.mkdtemp(prefix=".building-", dir=self.root))
try:
copy_root = building / "sandbox-copy"
dependency_root = building / "dependencies"
copy_root.mkdir(mode=0o700)
dependency_root.mkdir(mode=0o700)
budget = _SnapshotBudget()View on GitHub (pinned to d540b00184)
Solutions
- Move all cache.prepare / materialize / dependency_mounts usage inside the 'with TaskAssetCache(...) as cache:' block.
- If you need the cache longer, widen the with scope or delay close() until every arm has consumed the snapshot.
- Do not retain or reuse a reference to a cache after close().
Example fix
# before
with TaskAssetCache(root) as cache:
snapshot = cache.prepare(task, repo=repo, resolved_sha=sha)
# later, outside the with-block:
cache.prepare(other_task, repo=repo, resolved_sha=sha) # raises: cache closed
# after
with TaskAssetCache(root) as cache:
snapshot = cache.prepare(task, repo=repo, resolved_sha=sha)
other = cache.prepare(other_task, repo=repo, resolved_sha=sha)
snapshot.materialize(clone) # snapshot survives the cache Defensive patterns
Strategy: validation
Validate before calling
def assert_cache_open(cache):
if getattr(cache, "_closed", True):
raise RuntimeError("TaskAssetCache is closed; call prepare within its with-block") Type guard
def is_cache_open(cache) -> bool:
return not getattr(cache, "_closed", True) Prevention
- Keep all prepare/materialize/dependency_mounts calls inside the 'with TaskAssetCache(...) as cache:' block.
- Widen the with-scope rather than reusing a cache after close().
- Do not retain a cache reference past its context-manager exit.
When it happens
Trigger: Calling cache.prepare(...) after the 'with TaskAssetCache(...)' block exited, or after an explicit cache.close().
Common situations: A refactor that moved the prepare call outside the with block; reusing a closed cache across functions; holding a stale cache reference.
Related errors
- proposer output destination already exists: {overlay_dir}
- Embedder not initialized. Call initEmbedder() first.
- Embedding model not initialized. Run embedding pipeline firs
- {label} is unavailable: {path}: {exc}
- {label} must be a real non-symlink directory: {path}
AI-assisted analysis of abhigyanpatwari/GitNexus@d540b00184 (2026-08-12).
Data as JSON: /api/errors/71d4a57e6c68a56d.
Report an issue: GitHub.