rust-lang/rust · error
Failed to read contents of {path}: {err}
Error message
Failed to read contents of {path}: {err} What it means
This `panic!` fires inside `ensure_empty_dir` (utils.rs:180) when `fs::read_dir(path)` returns an error other than `NotFound`. `NotFound` is tolerated (nothing to clear), but failures such as `PermissionDenied`, a broken symlink, or an unreadable directory abort the cranelift build-system immediately. The path (already `create_dir_all`'d on the line above) and the OS error are formatted into the message.
Source
Thrown at compiler/rustc_codegen_cranelift/build_system/utils.rs:188
#[track_caller]
pub(crate) fn spawn_and_wait(mut cmd: Command) {
let status = cmd.spawn().unwrap().wait().unwrap();
if !status.success() {
eprintln!("{cmd:?} exited with status {:?}", status);
process::exit(1);
}
}
/// Create the specified directory if it doesn't exist yet and delete all contents.
pub(crate) fn ensure_empty_dir(path: &Path) {
fs::create_dir_all(path).unwrap();
let read_dir = match fs::read_dir(path) {
Ok(read_dir) => read_dir,
Err(err) if err.kind() == io::ErrorKind::NotFound => {
return;
}
Err(err) => {
panic!("Failed to read contents of {path}: {err}", path = path.display())
}
};
for entry in read_dir {
let entry = entry.unwrap();
if entry.file_type().unwrap().is_dir() {
match fs::remove_dir_all(entry.path()) {
Ok(()) => {}
Err(err) if err.kind() == io::ErrorKind::NotFound => {}
Err(err) => panic!("Failed to remove {path}: {err}", path = entry.path().display()),
}
} else {
match fs::remove_file(entry.path()) {
Ok(()) => {}
Err(err) if err.kind() == io::ErrorKind::NotFound => {}
Err(err) => panic!("Failed to remove {path}: {err}", path = entry.path().display()),
}
}
}View on GitHub (pinned to 22057b88b0)
Solutions
- Read the `err` field: `PermissionDenied` ⇒ `sudo chown -R $USER:$USER <path>` or `chmod -R u+rX <path>`.
- Manually wipe and recreate the path printed in the panic: `rm -rf <path> && mkdir -p <path>`, then re-run the build.
- Check for SELinux/AppArmor denials (`ausearch -m avc` / `dmesg`) and label the build tree accordingly.
- Move the build dir off network/FUSE filesystems onto a local ext4/xfs volume.
- Re-run from a clean slate: `./y.sh clean && ./y.sh prepare`.
Example fix
# before — ensure_empty_dir panics with PermissionDenied ./y.sh prepare # panics: Failed to read contents of /path/dir: Permission denied # after — fix perms then re-run sudo chown -R $USER:$USER /path/dir chmod -R u+rX /path/dir ./y.sh prepare
Defensive patterns
Strategy: validation
Validate before calling
// utils.rs read failure — the build tried to read a path that is missing,
// unreadable, or wrong. Validate existence + readability BEFORE invoking:
use std::path::Path;
fn readable(p: &Path) -> std::io::Result<()> {
let md = std::fs::metadata(p)?;
if md.is_dir() { return Err(std::io::Error::new(std::io::ErrorKind::IsADirectory, "is dir")); }
if md.permissions().readonly() { /* still readable, ok */ }
std::fs::read(p).map(|_| ()) // prove we can actually read the bytes
}
// Call readable(&path)? before the build step that consumes it. Try / catch
// Read defensively in your own driver, surfacing the exact cause:
fn read_or_diag(p: &std::path::Path) -> Vec<u8> {
match std::fs::read(p) {
Ok(b) => b,
Err(e) => {
eprintln!("read failed: {:?} kind={:?} exists={}",
p, e.kind(), p.exists());
std::process::exit(1);
}
}
} Prevention
- Verify the input path exists and is readable before the build step that needs it
- Do not move, delete, or overwrite build inputs while a build is running
- Pin absolute paths; relative paths break when the build changes its working dir
- On network shares, copy inputs locally first to avoid mid-read dropouts
When it happens
Trigger: Triggered when the cranelift build calls `ensure_empty_dir(target_dir)` (or any other path managed by `utils.rs`) and `read_dir` at line 182 returns an I/O error other than `NotFound`. Because `create_dir_all` succeeded one line earlier, this usually means the dir was created but is unreadable (mode bits, ACL, SELinux label, or a dangling symlink somewhere under it).
Common situations: Surfaces in CI or local cranelift builds when the target/download dir was created by a different user (e.g. an earlier `sudo ./y.sh`), when SELinux/AppArmor deny directory reads, or when the dir lives on a filesystem (FUSE, network) that fails `read_dir` transiently. Also seen after a crashed build leaves the tree in a half-state.
Related errors
- Failed to remove {path}: {err}
- Failed to remove {path}: {err}
- failed to create {dst:?}: {e}
- failed to copy {src:?}->{dst:?}: {e}
- prologue for {:?}
AI-assisted analysis of rust-lang/rust@22057b88b0 (2026-08-03).
Data as JSON: /data/errors/88c27891036948b9.json.
Report an issue: GitHub.