abhigyanpatwari/GitNexus · critical · ValueError

candidate sandbox does not bind the requested clone

Error message

candidate sandbox does not bind the requested clone

What it means

Thrown by apply_candidate_overlay (evolution.py:380) when the sandbox's bound clone (os.path.abspath(sandbox.clone)) does not equal the expected clone (os.path.abspath(worktree)). The harness refuses to write overlay bytes unless the sandbox session is bound to exactly the clone being modified, so that the staged writes land in the sandboxed clone and nowhere else.

Source

Thrown at eval/workflow_bench/evolution.py:380

def candidate_overlay_digest(overlay: Path) -> str:
    digest, _ = candidate_overlay_payload(overlay)
    return digest


def apply_candidate_overlay(
    overlay: Path,
    worktree: Path,
    *,
    sandbox: SandboxSession,
) -> str:
    """Safely copy and commit a prompt candidate inside its outer sandbox."""

    overlay = overlay.expanduser().absolute()
    expected_clone = Path(os.path.abspath(worktree.expanduser()))
    sandbox_clone = Path(os.path.abspath(sandbox.clone.expanduser()))
    if sandbox_clone != expected_clone:
        raise ValueError("candidate sandbox does not bind the requested clone")
    digest, payload = candidate_overlay_payload(overlay)
    relative_paths: list[str] = []
    for relative, content in payload:
        _replace_regular_file(worktree, relative, content)
        relative_paths.append(relative.as_posix())

    mkdir_command = ["/bin/mkdir", "-p", f"{SANDBOX_TMP}/wfbench-empty-hooks"]
    mkdir_result = sandbox.run(
        mkdir_command,
        timeout=60,
        env=build_sandbox_environment(),
    )
    if not mkdir_result.ok:
        raise ManagedProcessError(mkdir_command, mkdir_result)

    command, added = _sandbox_overlay_git(sandbox, ["add", "--", *relative_paths])
    if not added.ok:
        raise ManagedProcessError(command, added)

View on GitHub (pinned to d540b00184)

Solutions

  1. Pass exactly the same clone path used to create the sandbox session as worktree (both absolute, both non-symlinked).
  2. Compute both via os.path.abspath before comparison so they normalize identically.
  3. Use sandbox.clone directly as the worktree argument.

Example fix

# before: worktree differs from the sandbox's bound clone
sandbox = prepare_sandbox(clone=Path('repo-a'))
apply_candidate_overlay(overlay, Path('repo-b'), sandbox=sandbox)  # mismatch

# after: use the sandbox's own clone
with prepare_sandbox(clone=Path('repo-a').resolve()) as sandbox:
    apply_candidate_overlay(overlay, sandbox.clone, sandbox=sandbox)
Defensive patterns

Strategy: validation

Validate before calling

import os
from pathlib import Path

def sandbox_binds_clone(sandbox, worktree: Path) -> bool:
    return os.path.abspath(sandbox.clone.expanduser()) == os.path.abspath(worktree.expanduser())

Type guard

null

Try / catch

try:
    apply_candidate_overlay(overlay, worktree, sandbox=sandbox)
except ValueError as exc:
    if 'does not bind the requested clone' in str(exc):
        # pass sandbox.clone as worktree, then retry
        ...

Prevention

When it happens

Trigger: The caller passes a worktree path that differs from sandbox.clone — a different directory, an unresolved symlink, or a relative-vs-absolute mismatch after abspath normalization. Even a trailing-slash or symlink difference that abspath does not collapse will trip it.

Common situations: Creating the sandbox with one clone path and passing a different (or symlinked) worktree to apply_candidate_overlay; mixing a relative worktree with an absolute sandbox.clone; reusing a sandbox session across two different clones.

Related errors


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