Skip to content
Latchkey

Rust "build-script-build: Permission denied" in CI

Cargo compiled a build script but could not execute it. The output directory is mounted noexec, or the artifact lost its execute bit -- so running the build script fails with Permission denied.

What this error means

A crate with a build.rs fails to run its compiled build script with Permission denied (os error 13) even though the script compiled fine. Common when target/ or TMPDIR sits on a noexec mount.

cargo
error: failed to run custom build command for `ring v0.17.8`

Caused by:
  process didn't exit successfully: `.../build-script-build`
  Permission denied (os error 13)

Common causes

Output directory mounted noexec

If target/ or the temp dir cargo uses is on a filesystem mounted noexec, the compiled build script cannot be executed regardless of its permission bits.

Lost execute permission

A restored cache or a restrictive umask stripped the execute bit from the build-script binary, so the OS refuses to run it.

How to fix it

Point the build at an exec-capable location

Move the target/temp dir off any noexec mount.

Terminal
export CARGO_TARGET_DIR="${HOME}/target"
export TMPDIR="${HOME}/tmp"
mkdir -p "$TMPDIR"
cargo build --locked

Check the mount and permissions

  1. Run mount | grep noexec to see if the build dir is on a noexec filesystem.
  2. Ensure target/ is on a normal, exec-allowed volume.
  3. Do not cache build-script binaries with their execute bit stripped.

How to prevent it

  • Keep CARGO_TARGET_DIR/TMPDIR on exec-capable mounts.
  • Avoid noexec temp filesystems for Rust builds.
  • Preserve permissions when restoring build caches.

Frequently asked questions

What causes ""build-script-build: Permission denied""?
If target/ or the temp dir cargo uses is on a filesystem mounted noexec, the compiled build script cannot be executed regardless of its permission bits.
How do I fix "build-script-build: Permission denied"?
Move the target/temp dir off any noexec mount.
Can Latchkey fix this automatically?
Yes. Latchkey runs your GitHub Actions on managed runners that detect this failure, apply the fix, and retry the job automatically - self-healing is on by default.

Related guides

References

Latchkey auto-heals failures like this one - detected, fixed, and retried without you. Start free → 30-day trial · No credit card