{"id":"6498f009e320bc0b","repo":"rust-lang/rust","slug":"failed-to-remove-path-err-6498f0","errorCode":null,"errorMessage":"Failed to remove {path}: {err}","messagePattern":"Failed to remove (.+?): (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"compiler/rustc_codegen_cranelift/build_system/utils.rs","lineNumber":197,"sourceCode":"/// Create the specified directory if it doesn't exist yet and delete all contents.\npub(crate) fn ensure_empty_dir(path: &Path) {\n    fs::create_dir_all(path).unwrap();\n    let read_dir = match fs::read_dir(path) {\n        Ok(read_dir) => read_dir,\n        Err(err) if err.kind() == io::ErrorKind::NotFound => {\n            return;\n        }\n        Err(err) => {\n            panic!(\"Failed to read contents of {path}: {err}\", path = path.display())\n        }\n    };\n    for entry in read_dir {\n        let entry = entry.unwrap();\n        if entry.file_type().unwrap().is_dir() {\n            match fs::remove_dir_all(entry.path()) {\n                Ok(()) => {}\n                Err(err) if err.kind() == io::ErrorKind::NotFound => {}\n                Err(err) => panic!(\"Failed to remove {path}: {err}\", path = entry.path().display()),\n            }\n        } else {\n            match fs::remove_file(entry.path()) {\n                Ok(()) => {}\n                Err(err) if err.kind() == io::ErrorKind::NotFound => {}\n                Err(err) => panic!(\"Failed to remove {path}: {err}\", path = entry.path().display()),\n            }\n        }\n    }\n}\n\npub(crate) fn copy_dir_recursively(from: &Path, to: &Path) {\n    for entry in fs::read_dir(from).unwrap() {\n        let entry = entry.unwrap();\n        let filename = entry.file_name();\n        if filename == \".\" || filename == \"..\" {\n            continue;\n        }","sourceCodeStart":179,"sourceCodeEnd":215,"githubUrl":"https://github.com/rust-lang/rust/blob/22057b88b091743bc0fd8d592a9264f0a6951403/compiler/rustc_codegen_cranelift/build_system/utils.rs#L179-L215","documentation":"This `panic!` fires inside `ensure_empty_dir` (utils.rs:194-198) while iterating directory entries, when removing a sub-directory via `fs::remove_dir_all(entry.path())` returns an error other than `NotFound`. `NotFound` is tolerated (a concurrent remover already deleted it), but any other I/O failure (permission denied, dir not empty due to concurrent writes, busy handle) halts the cranelift build-system. The entry path and OS error are formatted into the message.","triggerScenarios":"Triggered when `ensure_empty_dir` walks the directory and `fs::remove_dir_all` at line 194 fails for a directory entry with a non-NotFound error. Reachable when the build tree contains a sub-directory whose contents are held open by another process, owned by another user, or on a read-only mount.","commonSituations":"Seen in cranelift local/CI builds when: a previous interrupted build left sub-dirs owned by root, an IDE/antivirus/Indexer holds handles on Windows, a process is actively writing into the dir (concurrent cargo), or a NFS/SMB mount returns stale file handles during recursive removal.","solutions":["Inspect the `err` and `path` in the panic message: `PermissionDenied` ⇒ fix ownership (`sudo chown -R $USER:$USER <entry path>`).","Ensure no other process (cargo, IDE, file indexer) is touching the build tree; on Windows close VS Code / disable Defender for the path.","Manually remove the offending sub-directory: `rm -rf <entry path>`, then re-run `./y.sh prepare`.","Re-run `ensure_empty_dir` after a `./y.sh clean` to start from a known-empty state.","Relocate the build dir off network/FUSE filesystems onto local disk."],"exampleFix":"# before — ensure_empty_dir panics removing a sub-dir\n./y.sh prepare\n# panics: Failed to remove /path/dir/sub: Permission denied\n\n# after — fix ownership of the sub-tree and re-run\nsudo chown -R $USER:$USER /path/dir\nrm -rf /path/dir/sub\n./y.sh prepare","handlingStrategy":"retry","validationCode":"// utils.rs:197 remove failure — same class as 56: transient/perms/lock.\n// Pre-flight: confirm the path is gone-able before the build removes it.\nuse std::path::Path;\nfn ensure_removable(p: &Path) -> std::io::Result<()> {\n    match std::fs::metadata(p) {\n        Ok(md) if md.permissions().readonly() =>\n            Err(std::io::Error::new(std::io::ErrorKind::PermissionDenied, \"readonly\")),\n        Ok(_) => Ok(()),\n        Err(e) if e.kind() == std::io::ErrorKind::NotFound => Ok(()), // nothing to remove\n        Err(e) => Err(e),\n    }\n}","typeGuard":null,"tryCatchPattern":"// Retry remove with backoff; surface final cause if it stays stuck.\nuse std::{fs, path::Path, thread, time::Duration};\nfn remove_retry(p: &Path, n: u32) -> std::io::Result<()> {\n    let mut last = None;\n    for a in 0..n {\n        match fs::remove_file(p) {\n            Ok(()) => return Ok(()),\n            Err(e) if e.kind() == std::io::ErrorKind::NotFound => return Ok(()),\n            Err(e) => { last = Some(e); if a + 1 < n { thread::sleep(Duration::from_millis(100 << a)); } }\n        }\n    }\n    Err(last.unwrap())\n}","preventionTips":["Make sure no other process holds the file open (editors, indexers, AV scans)","Confirm write/delete permission on the containing directory, not just the file","Prefer a clean build dir per CI run so stale locks don't accumulate","Retry with backoff; removal failures are frequently transient"],"tags":["rustc","cranelift","build-system","io","filesystem"],"analyzedSha":"22057b88b091743bc0fd8d592a9264f0a6951403","analyzedAt":"2026-08-03T08:09:25.915Z","schemaVersion":2}