{"record":{"id":"4a684d769a4b51d4","repo":"abhigyanpatwari/GitNexus","slug":"clone-object-is-hardlinked-to-host-storage-obj","errorCode":null,"errorMessage":"clone object is hardlinked to host storage: {obj}","messagePattern":"clone object is hardlinked to host storage: (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"critical","filePath":"eval/workflow_bench/runner_artifacts.py","lineNumber":324,"sourceCode":"        run_checked(\n            [\n                \"git\",\n                \"clone\",\n                \"--no-local\",\n                \"--no-hardlinks\",\n                \"--no-tags\",\n                \"--quiet\",\n                str(repo),\n                str(target),\n            ],\n            timeout=600,\n        )\n        alternates = target / \".git\" / \"objects\" / \"info\" / \"alternates\"\n        if alternates.exists():\n            raise RuntimeError(f\"clone unexpectedly has an external object alternate: {alternates}\")\n        for obj in (target / \".git\" / \"objects\").rglob(\"*\"):\n            if obj.is_file() and obj.stat().st_nlink > 1:\n                raise RuntimeError(f\"clone object is hardlinked to host storage: {obj}\")\n        for candidate in (ref, f\"origin/{ref}\"):\n            proc = run_managed(\n                [\"git\", \"-C\", str(target), \"checkout\", \"--detach\", \"--quiet\", candidate],\n                timeout=60,\n            )\n            if proc.ok:\n                return target\n        raise RuntimeError(f\"ref {ref!r} not found in clone of {repo}\")\n    except BaseException as primary:\n        if target.exists():\n            try:\n                shutil.rmtree(target)\n            except OSError as cleanup:\n                primary.add_note(f\"clone cleanup also failed: {type(cleanup).__name__}: {cleanup}\")\n        raise\n\n\ndef remove_clone(clone: Path) -> None:","sourceCodeStart":306,"sourceCodeEnd":342,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/d540b00184d71a896261ee02670da9a92d59d8f7/eval/workflow_bench/runner_artifacts.py#L306-L342","documentation":"Thrown by make_worktree during its post-clone isolation audit. Even with --no-hardlinks, the harness walks every file under target/.git/objects and rejects any with a link count (st_nlink) greater than 1, because a hardlinked object means the arm shares physical storage with the host and a mutation in one affects the other.","triggerScenarios":"For some object file `obj` under target/.git/objects, `obj.stat().st_nlink > 1`. A file there is hardlinked to a file outside the clone (or to another clone's object).","commonSituations":"A filesystem or git version that ignores --no-hardlinks; copying the worktree with `cp -l`/rsync --link-dest; a host with link-based dedup; the source repo and target on the same volume such that git fell back to hardlinks despite the flag.","solutions":["Ensure source repo and target live on different filesystems/devices so hardlinking is impossible, or rely on the --no-local transport the harness already requests.","Do not copy or rsync the resulting clone with hard-link options.","Use the harness's own make_worktree rather than a manual clone, since it already passes --no-local --no-hardlinks.","Upgrade git; older versions had bugs where --no-hardlinks was not honored in all paths."],"exampleFix":"// before — manual clone that may hardlink\nsubprocess.run(['git','clone', str(repo), str(target)])  # same-volume -> hardlinks\n\n// after — use the harness helper which forces --no-local --no-hardlinks\nfrom eval.workflow_bench.runner_artifacts import make_worktree\ntarget = make_worktree(repo, ref, parent=tempfile.gettempdir())","handlingStrategy":"validation","validationCode":"from pathlib import Path\n\ndef no_hardlinked_objects(target: Path) -> bool:\n    objects = target / '.git' / 'objects'\n    return all(f.stat().st_nlink == 1 for f in objects.rglob('*') if f.is_file())","typeGuard":"null","tryCatchPattern":"try:\n    make_worktree(repo, ref, parent)\nexcept RuntimeError as e:\n    if 'hardlinked to host storage' in str(e):\n        # move source/target to different filesystems, or stop copying with -l\n        raise\n    raise","preventionTips":["Always use make_worktree (which passes --no-local --no-hardlinks) instead of a manual clone.","Keep source repo and target on different filesystems so hardlinking is impossible.","Never rsync/cp the clone with --link-dest or -l.","After any manual clone, assert no_hardlinked_objects(target) before proceeding."],"tags":["git-clone","sandbox-isolation","hardlinks","workflow-bench"],"backgroundTag":null,"analyzedSha":"d540b00184d71a896261ee02670da9a92d59d8f7","analyzedAt":"2026-08-12T19:50:25.132Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}