abhigyanpatwari/GitNexus · error · SandboxError

{label} target cannot be a symlink: {relative}

Error message

{label} target cannot be a symlink: {relative}

What it means

Raised by _prepare_clone_target when the leaf component of the target path already exists and os.stat(follow_symlinks=False) reports it as a symlink. A symlink leaf could redirect a mount or file write outside the clone, so staging aborts rather than follow it. This is a hard trust-boundary refusal: the leaf must be a real directory or regular file.

Source

Thrown at eval/workflow_bench/proposer_sandbox.py:612

        for part in relative.parts[:-1]:
            try:
                os.mkdir(part, mode=0o700, dir_fd=current_fd)
            except FileExistsError:
                pass
            try:
                next_fd = os.open(part, flags | nofollow, dir_fd=current_fd)
            except OSError as exc:
                raise SandboxError(f"{label} target has a non-directory or symlink parent: {relative}") from exc
            os.close(current_fd)
            current_fd = next_fd

        leaf = relative.parts[-1]
        try:
            mode = os.stat(leaf, dir_fd=current_fd, follow_symlinks=False).st_mode
        except FileNotFoundError:
            mode = None
        if mode is not None and stat.S_ISLNK(mode):
            raise SandboxError(f"{label} target cannot be a symlink: {relative}")
        if directory is True:
            if mode is None:
                os.mkdir(leaf, mode=0o700, dir_fd=current_fd)
            elif not stat.S_ISDIR(mode):
                raise SandboxError(f"{label} directory target has the wrong type: {relative}")
        elif directory is False:
            if mode is None:
                file_flags = os.O_WRONLY | os.O_CREAT | os.O_EXCL | nofollow
                file_fd = os.open(leaf, file_flags, 0o600, dir_fd=current_fd)
                os.close(file_fd)
            elif not stat.S_ISREG(mode):
                raise SandboxError(f"{label} file target has the wrong type: {relative}")
        elif mode is not None and not (stat.S_ISREG(mode) or stat.S_ISDIR(mode)):
            raise SandboxError(f"{label} target has the wrong type: {relative}")
    finally:
        os.close(current_fd)
    return clone / Path(*relative.parts)

View on GitHub (pinned to d540b00184)

Solutions

  1. Inspect the leaf path in the error: `ls -la <worktree>/<leaf>` and confirm it is a symlink (`readlink`).
  2. Remove the offending symlink from the repo at that path, or change the task target so its leaf is not a pre-existing symlink.
  3. If a setup step created it, ensure setup writes real directories/files (not symlinks) at harness-managed targets.
  4. Re-run with a clean worktree to confirm the symlink is tracked rather than generated.

Example fix

// before — target leaf is a symlink in the repo
<worktree>/.vite-temp -> /tmp/vite
// after — remove the tracked symlink so the harness can create a real dir
git rm .vite-temp   # let _prepare_clone_target mkdir it
Defensive patterns

Strategy: validation

Validate before calling

import os, stat
from pathlib import PurePosixPath

def leaf_is_not_symlink(clone: Path, relative: str) -> bool:
    # open the parent dir with O_NOFOLLOW, then lstat the leaf
    parts = PurePosixPath(relative).parts
    pfd = os.open(clone, os.O_RDONLY | os.O_DIRECTORY | os.O_NOFOLLOW)
    try:
        for p in parts[:-1]:
            nxt = os.open(p, os.O_RDONLY | os.O_DIRECTORY | os.O_NOFOLLOW, dir_fd=pfd)
            os.close(pfd); pfd = nxt
        try:
            mode = os.stat(parts[-1], dir_fd=pfd, follow_symlinks=False).st_mode
            return not stat.S_ISLNK(mode)
        except FileNotFoundError:
            return True  # absent leaf is fine
    finally:
        os.close(pfd)

Try / catch

from .proposer_sandbox import SandboxError

try:
    target = _prepare_clone_target(clone, PurePosixPath(rel), directory=None, label='mount')
except SandboxError as exc:
    # leaf is a symlink; remove it or reroute the target
    raise

Prevention

When it happens

Trigger: _prepare_clone_target reaches the leaf (relative.parts[-1]); the leaf exists; `stat.S_ISLNK(mode)` is true. This happens when a task target path's final component is a tracked or pre-existing symlink inside the clone (e.g. a dependency mount point committed as a symlink).

Common situations: A repo ships a symlink at a path the harness wants to use as a mount placeholder or file target (common in monorepos with `node_modules` or `dist` symlinks); a previous setup step replaced a directory/file with a symlink; cross-platform checkouts materialize a symlink where a file was expected.

Related errors


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