codex - 💡(How to fix) Fix Sandbox writable_roots bind mounts break hardlinks across roots (uv cache to .venv)

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

Root Cause

Omitted/redacted because the full report includes local machine paths. Relevant parts:

Fix Action

Fix / Workaround

Workarounds:

Code Example

{
  "codexVersion": "0.133.0",
  "checks": {
    "sandbox.helpers": {
      "status": "ok",
      "details": {
        "approval policy": "OnRequest",
        "filesystem sandbox": "restricted",
        "network sandbox": "enabled"
      }
    },
    "terminal.env": {
      "details": {
        "terminal": "Windows Terminal",
        "WSL_DISTRO_NAME": "present"
      }
    }
  }
}

---

warning: Failed to hardlink files; falling back to full copy. This may lead to degraded performance.
         If the cache and target directories are on different filesystems, hardlinking may not be supported.

---

TARGET              SOURCE
<home>/.cache/uv    /dev/sdd[<home>/.cache/uv]
<repo>              /dev/sdd[<repo>]

---

ln: failed to create hard link '<repo>/api/.venv/codex-hardlink-dest.tmp' => '<home>/.cache/uv/codex-hardlink-source.tmp': Invalid cross-device link

---

<same inode> 2 <repo>/codex-hardlink-source.tmp
<same inode> 2 <repo>/api/.venv/codex-hardlink-dest.tmp

---

<home>/.cache/uv
<repo>

---

uv cache dir
readlink --canonicalize api/.venv
df --print-type <home>/.cache/uv api/.venv
findmnt --target <home>/.cache/uv --output TARGET,SOURCE,FSTYPE,OPTIONS
findmnt --target "$PWD/api/.venv" --output TARGET,SOURCE,FSTYPE,OPTIONS

---

src=<home>/.cache/uv/codex-hardlink-source.tmp
dst="$PWD/api/.venv/codex-hardlink-dest.tmp"
rm --force "$src" "$dst"
printf 'hardlink-test\n' > "$src"
ln "$src" "$dst"

---

Invalid cross-device link

---

src="$PWD/codex-hardlink-source.tmp"
dst="$PWD/api/.venv/codex-hardlink-dest.tmp"
rm --force "$src" "$dst"
printf 'hardlink-test\n' > "$src"
ln "$src" "$dst"
stat --format '%i %h %n' "$src" "$dst"
RAW_BUFFERClick to expand / collapse

What version of Codex CLI is running?

codex-cli 0.133.0

What subscription do you have?

Plus

Which model were you using?

gpt-5.5

What platform is your computer?

Linux 6.6.114.1-microsoft-standard-WSL2 x86_64

What terminal emulator and version are you using (if applicable)?

Windows Terminal, WSL2

Codex doctor report

Omitted/redacted because the full report includes local machine paths. Relevant parts:

{
  "codexVersion": "0.133.0",
  "checks": {
    "sandbox.helpers": {
      "status": "ok",
      "details": {
        "approval policy": "OnRequest",
        "filesystem sandbox": "restricted",
        "network sandbox": "enabled"
      }
    },
    "terminal.env": {
      "details": {
        "terminal": "Windows Terminal",
        "WSL_DISTRO_NAME": "present"
      }
    }
  }
}

What issue are you seeing?

When Codex runs with workspace-write and multiple writable roots, each writable root appears to be exposed as a separate bind mount. This makes hardlinks fail across writable roots even when both roots are backed by the same ext4 device.

The concrete symptom was uv warning while running a Python tool:

warning: Failed to hardlink files; falling back to full copy. This may lead to degraded performance.
         If the cache and target directories are on different filesystems, hardlinking may not be supported.

In this setup:

  • uv cache root is one writable root: <home>/.cache/uv
  • project/worktree is another writable root: <repo>
  • virtualenv is inside the project root: <repo>/api/.venv

Inside the Codex sandbox, df shows both paths on the same ext4 device, but findmnt shows them as separate bind mounts:

TARGET              SOURCE
<home>/.cache/uv    /dev/sdd[<home>/.cache/uv]
<repo>              /dev/sdd[<repo>]

Attempting a normal hardlink from the uv cache root into the project root fails:

ln: failed to create hard link '<repo>/api/.venv/codex-hardlink-dest.tmp' => '<home>/.cache/uv/codex-hardlink-source.tmp': Invalid cross-device link

But hardlinking within the project writable root succeeds, including into the same .venv:

<same inode> 2 <repo>/codex-hardlink-source.tmp
<same inode> 2 <repo>/api/.venv/codex-hardlink-dest.tmp

This looks related to #8636 and #10864, but those are Cargo/Rust cases. This report is specifically about hardlinks across multiple Codex writable roots, reproduced with plain ln and surfaced by uv.

What steps can reproduce the bug?

Use a workspace-write Codex session with both of these as writable roots:

<home>/.cache/uv
<repo>

Then run:

uv cache dir
readlink --canonicalize api/.venv
df --print-type <home>/.cache/uv api/.venv
findmnt --target <home>/.cache/uv --output TARGET,SOURCE,FSTYPE,OPTIONS
findmnt --target "$PWD/api/.venv" --output TARGET,SOURCE,FSTYPE,OPTIONS

Then test cross-root hardlinking:

src=<home>/.cache/uv/codex-hardlink-source.tmp
dst="$PWD/api/.venv/codex-hardlink-dest.tmp"
rm --force "$src" "$dst"
printf 'hardlink-test\n' > "$src"
ln "$src" "$dst"

Observed:

Invalid cross-device link

Control test inside the project writable root:

src="$PWD/codex-hardlink-source.tmp"
dst="$PWD/api/.venv/codex-hardlink-dest.tmp"
rm --force "$src" "$dst"
printf 'hardlink-test\n' > "$src"
ln "$src" "$dst"
stat --format '%i %h %n' "$src" "$dst"

Observed: succeeds with the same inode and link count 2.

What is the expected behavior?

If two writable roots are backed by the same underlying filesystem, hardlinks between them should either work, or Codex should document that each writable root is isolated as a separate mount and cross-root hardlinks are expected to fail.

This matters for package managers and build tools that optimize by hardlinking from caches into project-local environments, such as uv cache to .venv.

Additional information

Workarounds:

  • UV_LINK_MODE=copy suppresses the uv warning and uses copies instead of hardlinks.
  • Moving UV_CACHE_DIR under the project writable root should also avoid the warning, but creates project-local cache clutter.

Related issues:

  • #8636
  • #10864

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

codex - 💡(How to fix) Fix Sandbox writable_roots bind mounts break hardlinks across roots (uv cache to .venv)