{"record":{"id":"80c287d6a17a947b","repo":"abhigyanpatwari/GitNexus","slug":"candidate-destination-must-be-a-regular-non-symlin","errorCode":null,"errorMessage":"candidate destination must be a regular non-symlink file: {relative}","messagePattern":"candidate destination must be a regular non-symlink file: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"critical","filePath":"eval/workflow_bench/evolution.py","lineNumber":197,"sourceCode":"                pass\n            try:\n                child = os.open(part, directory_flags, dir_fd=descriptor)\n            except OSError as exc:\n                raise ValueError(\n                    f\"candidate destination parent must be a real directory: {relative.parent}: {exc}\"\n                ) from exc\n            os.close(descriptor)\n            descriptor = child\n\n        leaf = relative.name\n        try:\n            existing = os.stat(leaf, dir_fd=descriptor, follow_symlinks=False)\n        except FileNotFoundError:\n            existing = None\n        except OSError as exc:\n            raise ValueError(f\"candidate destination is unreadable: {relative}: {exc}\") from exc\n        if existing is not None and (stat.S_ISLNK(existing.st_mode) or not stat.S_ISREG(existing.st_mode)):\n            raise ValueError(f\"candidate destination must be a regular non-symlink file: {relative}\")\n\n        temporary = f\".wfbench-overlay-{secrets.token_hex(12)}\"\n        temp_descriptor = os.open(\n            temporary,\n            os.O_WRONLY | os.O_CREAT | os.O_EXCL | getattr(os, \"O_NOFOLLOW\", 0),\n            0o600,\n            dir_fd=descriptor,\n        )\n        try:\n            view = memoryview(content)\n            while view:\n                written = os.write(temp_descriptor, view)\n                if written <= 0:\n                    raise OSError(\"short write while staging candidate overlay\")\n                view = view[written:]\n            os.fchmod(temp_descriptor, 0o644)\n        except BaseException:\n            try:","sourceCodeStart":179,"sourceCodeEnd":215,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/d540b00184d71a896261ee02670da9a92d59d8f7/eval/workflow_bench/evolution.py#L179-L215","documentation":"Thrown by _replace_regular_file (evolution.py:197) when the existing leaf in the clone is a symlink or any non-regular file (directory, fifo, device). The harness only atomically os.replace's a staged temp file onto a regular non-symlink file (or a not-yet-existing leaf); it will never overwrite a symlink, because that could redirect the write outside the clone.","triggerScenarios":"The clone already has a symlink, directory, fifo, or device node at the exact overlay destination path. A symlink leaf is treated as a security violation because os.replace would follow/replace the link target rather than the link slot.","commonSituations":"A previous tool symlinked .claude/skills/gitnexus-work to a shared dir; the clone ships a symlink at that path; leftover directories from a malformed prior overlay.","solutions":["Remove the offending symlink/non-regular file at the leaf path in the clone.","Reset the clone to a clean checkout (git clean -fdx / fresh clone) so the destination is either absent or a real regular file.","Verify with os.path.islink and stat.S_ISREG before invoking the harness."],"exampleFix":"# before: clone has a symlink at the destination\nclone/.claude/skills/gitnexus-work -> /shared/skills  # symlink -> rejected\n\n# after: replace with a real regular file (or delete it)\nimport os, stat\np = clone / '.claude/skills/gitnexus-work/SKILL.md'\nif os.path.islink(p) or not stat.S_ISREG(p.lstat().st_mode):\n    os.unlink(p)  # harness will create a fresh regular file","handlingStrategy":"validation","validationCode":"import os, stat\nfrom pathlib import Path\n\ndef leaf_is_regular_or_absent(clone: Path, rel: Path) -> bool:\n    leaf = clone / rel\n    try:\n        m = leaf.lstat().st_mode\n    except FileNotFoundError:\n        return True\n    return stat.S_ISREG(m) and not stat.S_ISLNK(m)","typeGuard":"import os, stat\nfrom pathlib import Path\n\ndef is_regular_or_absent(p: Path) -> bool:\n    try:\n        m = p.lstat().st_mode\n    except FileNotFoundError:\n        return True\n    return stat.S_ISREG(m) and not stat.S_ISLNK(m)","tryCatchPattern":"try:\n    apply_candidate_overlay(overlay, worktree, sandbox=sandbox)\nexcept ValueError as exc:\n    if 'regular non-symlink file' in str(exc):\n        # unlink the symlink/dir at the named path, then retry\n        ...","preventionTips":["Never symlink the destination skill files in the clone.","git clean -fdx the clone before benchmark runs to remove stray nodes.","Treat this as a security signal: a symlink leaf could redirect writes."],"tags":["security","symlink","filesystem","overlay","trust-boundary"],"backgroundTag":null,"analyzedSha":"d540b00184d71a896261ee02670da9a92d59d8f7","analyzedAt":"2026-08-12T19:50:25.132Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}