← Debugging Guides

阅读中文版本

Cargo Permission Denied — Target Directory Not Writable

Fix cargo build permission denied errors by correcting ownership of target/, avoiding shared target dirs across users, and clearing stale locks.

intermediatedebuggingrustcargopermissions

Symptoms

  • cargo build fails with "Permission denied (os error 13)" under target/
  • The error appears after building as root once
  • A CI cache mounted read-only breaks the build

Possible causes

  • A previous build ran as another user (often root), making target/ files unwritable
  • The target directory is on a read-only mount or a shared cache with wrong permissions
  • A stale .cargo-lock is held by a dead process

Diagnosis steps

Inspect ownership and permissions of target

ls -ld target target/debug && stat -c "%U %a" target/debug

Interpretation

Root-owned files under a user directory explain the write failure.

Reproduce with a clean target directory

CARGO_TARGET_DIR=/tmp/cargo-target cargo build

Interpretation

Building into a writable temp dir succeeds, isolating the problem to the original target.

Root cause

Cargo writes fingerprints, rlibs, and locks under target/. If those files are owned by another user or live on a read-only mount, every write returns os error 13 before compilation can proceed.

Fix

Fix ownership (chown -R you target), avoid running builds as root, give CI a writable CARGO_TARGET_DIR, and remove stale locks with cargo clean or by deleting target/.cargo-lock.

Risk note

chown -R on a container target can break other mounts; scope the change to the project directory only.

Verify the fix

Rerun cargo build as the normal user and confirm it completes; verify target files are owned by that user.

Symptoms

When you hit “Cargo Permission Denied — Target Directory Not Writable”, guessing wastes time. The guide below follows evidence: reproduce the symptom, run targeted diagnostics, identify the root cause, apply the fix, and verify it with concrete checks.

Observed symptoms include:

  • cargo build fails with “Permission denied (os error 13)” under target/
  • The error appears after building as root once
  • A CI cache mounted read-only breaks the build

Reproduce and Diagnose

Reproduce the failure in isolation before changing any code. Work through the checks below in order; each one narrows the search space.

Step 1: Inspect ownership and permissions of target

ls -ld target target/debug && stat -c "%U %a" target/debug

Root-owned files under a user directory explain the write failure.

Step 2: Reproduce with a clean target directory

CARGO_TARGET_DIR=/tmp/cargo-target cargo build

Building into a writable temp dir succeeds, isolating the problem to the original target.

Likely contributors, in order of frequency:

  • A previous build ran as another user (often root), making target/ files unwritable
  • The target directory is on a read-only mount or a shared cache with wrong permissions
  • A stale .cargo-lock is held by a dead process

Root Cause

Cargo writes fingerprints, rlibs, and locks under target/. If those files are owned by another user or live on a read-only mount, every write returns os error 13 before compilation can proceed.

The Fix

Fix ownership (chown -R you target), avoid running builds as root, give CI a writable CARGO_TARGET_DIR, and remove stale locks with cargo clean or by deleting target/.cargo-lock.

Watch out: chown -R on a container target can break other mounts; scope the change to the project directory only.

# inspect and fix ownership
ls -ld target
sudo chown -R "$USER":"$USER" target

# or build into a clean, writable directory
CARGO_TARGET_DIR=/tmp/cargo-target cargo build --release

# clear a stale lock if a dead process held it
rm -f target/.cargo-lock

Verify and Prevent

Rerun cargo build as the normal user and confirm it completes; verify target files are owned by that user.

Once verified, add a regression test that reproduces the original symptom so the failure cannot silently return.

This class of failure is usually environmental rather than pure logic, so capture the exact command, the environment variables, and the working directory in your bug report. Reproduce it in the smallest possible script, then widen the scope only once the minimal case is understood. A short written checklist for this failure mode saves hours the next time it appears.