rust-lang/cargo · warning · anyhow::Error

failed to read path `{path:?}`

Error message

failed to read path `{path:?}`

What it means

Raised in `GlobalCacheTracker::read_dir_with_filter` (src/workspace/global_cache_tracker.rs:680) when `path.read_dir()` fails with an io::Error whose kind is NOT `NotFound` (NotFound is tolerated and returns an empty vec). Any other IO failure — permission denied, broken symlink, I/O error — is wrapped with `failed to read path \"<path>\"` context.

Source

Thrown at src/workspace/global_cache_tracker.rs:681

    fn list_dir_names(path: &Path) -> CargoResult<Vec<String>> {
        Self::read_dir_with_filter(path, &|entry| {
            entry.file_type().map_or(false, |ty| ty.is_dir())
        })
    }

    /// Returns a list of names in a directory, filtered by the given callback.
    fn read_dir_with_filter(
        path: &Path,
        filter: &dyn Fn(&std::fs::DirEntry) -> bool,
    ) -> CargoResult<Vec<String>> {
        let entries = match path.read_dir() {
            Ok(e) => e,
            Err(e) => {
                if e.kind() == std::io::ErrorKind::NotFound {
                    return Ok(Vec::new());
                } else {
                    return Err(
                        anyhow::Error::new(e).context(format!("failed to read path `{path:?}`"))
                    );
                }
            }
        };
        let names = entries
            .filter_map(|entry| entry.ok())
            .filter(|entry| filter(entry))
            .filter_map(|entry| entry.file_name().into_string().ok())
            .collect();
        Ok(names)
    }

    /// Synchronizes the database to match the files on disk.
    ///
    /// This performs the following cleanups:
    ///
    /// 1. Remove entries from the database that are missing on disk.
    /// 2. Adds missing entries to the database that are on disk (such as when

View on GitHub (pinned to 0e07a15537)

Solutions

  1. Fix permissions so cargo can read the directory (`chmod -R u+rX ~/.cargo`).
  2. Remove broken symlinks or corrupt cache entries (`cargo cache clean` or manual cleanup of the named path).
  3. Ensure no other process is mutating `$CARGO_HOME` while cargo runs; retry if it was transient (I/O error).

Example fix

# grant read+execute on the offending cache dir
chmod -R u+rX ~/.cargo/registry/cache
# or clean a corrupt cache
cargo cache clean
Defensive patterns

Strategy: try-catch

Validate before calling

use std::path::Path;
fn readable_dir(p: &Path) -> bool {
    match std::fs::metadata(p) {
        Ok(m) => m.is_dir() && std::fs::read_dir(p).is_ok(),
        Err(_) => false,
    }
}
// before cache operations, verify readable_dir on $CARGO_HOME subdirs

Try / catch

// treat non-NotFound read_dir errors as best-effort skips
let names = match path.read_dir() {
    Ok(e) => e.filter_map(|r| r.ok()).map(|e| e.file_name().to_string_lossy().into_owned()).collect::<Vec<_>>(),
    Err(e) if e.kind() == std::io::ErrorKind::NotFound => Vec::new(),
    Err(_) => Vec::new(), // swallow permission/IO errors instead of failing
};

Prevention

When it happens

Trigger: `cargo cache` / global cache tracking walks a directory under `$CARGO_HOME` (e.g. `registry/cache`, `git/db`) and `read_dir` returns a non-NotFound error: EACCES on a dir cargo cannot traverse, EIO, a broken symlink target, or a filesystem error.

Common situations: Permissions on `~/.cargo` set so some subdirs are not readable by the cargo user; partial extraction leaving broken symlinks; NFS/share hiccups; another process modifying the cache concurrently; disk errors.

Related errors


AI-assisted analysis of rust-lang/cargo@0e07a15537 (2026-08-06). Data as JSON: /data/errors/dd14c5d606f98645.json. Report an issue: GitHub.