rust-lang/rust · error
failed to copy {src:?}->{dst:?}: {e}
Error message
failed to copy {src:?}->{dst:?}: {e} What it means
Panics inside copy_dir_recursively when fs::copy fails to copy a regular file from src to dst. Like error 60 this runs during the prepare stage that stages rustc sources into the build target. The panic halts staging because every source file is expected to copy cleanly.
Source
Thrown at compiler/rustc_codegen_cranelift/build_system/utils.rs:222
}
}
}
}
pub(crate) fn copy_dir_recursively(from: &Path, to: &Path) {
for entry in fs::read_dir(from).unwrap() {
let entry = entry.unwrap();
let filename = entry.file_name();
if filename == "." || filename == ".." {
continue;
}
let src = from.join(&filename);
let dst = to.join(&filename);
if entry.metadata().unwrap().is_dir() {
fs::create_dir(&dst).unwrap_or_else(|e| panic!("failed to create {dst:?}: {e}"));
copy_dir_recursively(&src, &dst);
} else {
fs::copy(&src, &dst).unwrap_or_else(|e| panic!("failed to copy {src:?}->{dst:?}: {e}"));
}
}
}
static IN_GROUP: AtomicBool = AtomicBool::new(false);
pub(crate) struct LogGroup {
is_gha: bool,
}
impl LogGroup {
pub(crate) fn guard(name: &str) -> LogGroup {
let is_gha = env::var("GITHUB_ACTIONS").is_ok();
assert!(!IN_GROUP.swap(true, Ordering::SeqCst));
if is_gha {
eprintln!("::group::{name}");
}
View on GitHub (pinned to 22057b88b0)
Solutions
- Re-run `./y.rs prepare` from a clean checkout so the source tree is not mutating during the copy.
- Verify read permission on src: `ls -l <src>` (look for mode and owner).
- Check the dst filesystem is writable and has free space: `df -h <dst>` and `touch <dst-dir>/.probe`.
- On Windows, exclude the build directory from antivirus real-time scanning.
Example fix
// before
fs::copy(&src, &dst).unwrap_or_else(|e| panic!("failed to copy {src:?}->{dst:?}: {e}"));
// after
fs::copy(&src, &dst).unwrap_or_else(|e| match e.kind() {
io::ErrorKind::AlreadyExists => { /* re-copy is fine, fall through */ fs::copy(&src, &dst).unwrap() }
_ => panic!("failed to copy {src:?}->{dst:?}: {e}"),
}); Defensive patterns
Strategy: validation
Validate before calling
use std::path::Path;
fn ensure_copyable(src: &Path, dst: &Path) -> Result<(), String> {
let sm = std::fs::metadata(src).map_err(|e| format!("src {:?} not readable: {}", src, e))?;
if !sm.is_file() { return Err(format!("src {:?} is not a regular file", src)); }
let parent = dst.parent().ok_or_else(|| format!("dst {:?} has no parent", dst))?;
if !parent.exists() { return Err(format!("dst parent {:?} missing", parent)); }
let pm = std::fs::metadata(parent).map_err(|e| format!("cannot stat dst parent: {}", e))?;
if pm.permissions().readonly() { return Err(format!("dst parent {:?} is readonly", parent)); }
if dst.exists() && dst.metadata().map(|m| m.permissions().readonly()).unwrap_or(false) {
return Err(format!("dst {:?} exists and is readonly", dst));
}
Ok(())
} Try / catch
use std::panic;
match panic::catch_unwind(|| fs::copy(src, dst)) {
Ok(Ok(n)) => { /* copied n bytes */ }
Ok(Err(e)) => return Err(format!("io copy failed: {}", e)),
Err(_) => { /* remove partial dst, surface as fatal build error */ }
} Prevention
- Verify src exists and is a regular file before triggering the copy.
- Make sure the destination parent is writable and not on a full or readonly filesystem.
- Avoid placing dst where a concurrent process may lock it (e.g. antivirus, indexer).
- If a copy panics, delete the partial destination before retrying to avoid stale artifacts.
When it happens
Trigger: Reached for every non-directory entry while walking `from` during copy_dir_recursively. The panic message shows both src and dst plus the io::Error returned by std::fs::copy.
Common situations: src file is removed/renamed between read_dir and copy (TOCTOU, common with editor temp files or `.git` mutating underneath); dst is on a read-only or full filesystem; permission bits on src forbid reading (e.g. staged under a mode-0600 dir); cross-filesystem copy hits an immutable/append-only flag; antivirus/Defender locking the file on Windows.
Related errors
- failed to create {dst:?}: {e}
- Failed to remove {path}: {err}
- Failed to read contents of {path}: {err}
- Failed to remove {path}: {err}
- Path component {:?} of path {} is an invalid filename
AI-assisted analysis of rust-lang/rust@22057b88b0 (2026-08-03).
Data as JSON: /data/errors/47575a07e710229e.json.
Report an issue: GitHub.