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.
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/debugInterpretation
Root-owned files under a user directory explain the write failure.
Reproduce with a clean target directory
CARGO_TARGET_DIR=/tmp/cargo-target cargo buildInterpretation
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.