{"record":{"id":"bb71709742cbe359","repo":"abhigyanpatwari/GitNexus","slug":"label-target-cannot-be-a-symlink-relative","errorCode":null,"errorMessage":"{label} target cannot be a symlink: {relative}","messagePattern":"(.+?) target cannot be a symlink: (.+?)","errorType":"exception","errorClass":"SandboxError","httpStatus":null,"severity":"error","filePath":"eval/workflow_bench/proposer_sandbox.py","lineNumber":612,"sourceCode":"        for part in relative.parts[:-1]:\n            try:\n                os.mkdir(part, mode=0o700, dir_fd=current_fd)\n            except FileExistsError:\n                pass\n            try:\n                next_fd = os.open(part, flags | nofollow, dir_fd=current_fd)\n            except OSError as exc:\n                raise SandboxError(f\"{label} target has a non-directory or symlink parent: {relative}\") from exc\n            os.close(current_fd)\n            current_fd = next_fd\n\n        leaf = relative.parts[-1]\n        try:\n            mode = os.stat(leaf, dir_fd=current_fd, follow_symlinks=False).st_mode\n        except FileNotFoundError:\n            mode = None\n        if mode is not None and stat.S_ISLNK(mode):\n            raise SandboxError(f\"{label} target cannot be a symlink: {relative}\")\n        if directory is True:\n            if mode is None:\n                os.mkdir(leaf, mode=0o700, dir_fd=current_fd)\n            elif not stat.S_ISDIR(mode):\n                raise SandboxError(f\"{label} directory target has the wrong type: {relative}\")\n        elif directory is False:\n            if mode is None:\n                file_flags = os.O_WRONLY | os.O_CREAT | os.O_EXCL | nofollow\n                file_fd = os.open(leaf, file_flags, 0o600, dir_fd=current_fd)\n                os.close(file_fd)\n            elif not stat.S_ISREG(mode):\n                raise SandboxError(f\"{label} file target has the wrong type: {relative}\")\n        elif mode is not None and not (stat.S_ISREG(mode) or stat.S_ISDIR(mode)):\n            raise SandboxError(f\"{label} target has the wrong type: {relative}\")\n    finally:\n        os.close(current_fd)\n    return clone / Path(*relative.parts)\n","sourceCodeStart":594,"sourceCodeEnd":630,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/d540b00184d71a896261ee02670da9a92d59d8f7/eval/workflow_bench/proposer_sandbox.py#L594-L630","documentation":"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.","triggerScenarios":"_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).","commonSituations":"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.","solutions":["Inspect the leaf path in the error: `ls -la <worktree>/<leaf>` and confirm it is a symlink (`readlink`).","Remove the offending symlink from the repo at that path, or change the task target so its leaf is not a pre-existing symlink.","If a setup step created it, ensure setup writes real directories/files (not symlinks) at harness-managed targets.","Re-run with a clean worktree to confirm the symlink is tracked rather than generated."],"exampleFix":"// before — target leaf is a symlink in the repo\n<worktree>/.vite-temp -> /tmp/vite\n// after — remove the tracked symlink so the harness can create a real dir\ngit rm .vite-temp   # let _prepare_clone_target mkdir it","handlingStrategy":"validation","validationCode":"import os, stat\nfrom pathlib import PurePosixPath\n\ndef leaf_is_not_symlink(clone: Path, relative: str) -> bool:\n    # open the parent dir with O_NOFOLLOW, then lstat the leaf\n    parts = PurePosixPath(relative).parts\n    pfd = os.open(clone, os.O_RDONLY | os.O_DIRECTORY | os.O_NOFOLLOW)\n    try:\n        for p in parts[:-1]:\n            nxt = os.open(p, os.O_RDONLY | os.O_DIRECTORY | os.O_NOFOLLOW, dir_fd=pfd)\n            os.close(pfd); pfd = nxt\n        try:\n            mode = os.stat(parts[-1], dir_fd=pfd, follow_symlinks=False).st_mode\n            return not stat.S_ISLNK(mode)\n        except FileNotFoundError:\n            return True  # absent leaf is fine\n    finally:\n        os.close(pfd)","typeGuard":null,"tryCatchPattern":"from .proposer_sandbox import SandboxError\n\ntry:\n    target = _prepare_clone_target(clone, PurePosixPath(rel), directory=None, label='mount')\nexcept SandboxError as exc:\n    # leaf is a symlink; remove it or reroute the target\n    raise","preventionTips":["Do not commit symlinks at paths the harness uses as mount placeholders.","Ensure setup steps create real files/dirs, never symlinks, at harness-managed leaves.","Validate target leaves with lstat before staging."],"tags":["sandbox","symlink-guard","trust-boundary","task-assets","path-validation"],"backgroundTag":null,"analyzedSha":"d540b00184d71a896261ee02670da9a92d59d8f7","analyzedAt":"2026-08-12T19:50:25.132Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}