rust-lang/rust · error · anyhow::Error

Failed to get metadata for config file

Error message

Failed to get metadata for config file {:?}

What it means

Returned by rustfmt's config loader get_toml_path when fs::metadata on a candidate config file (rustfmt.toml / .rustfmt.toml) returns an error other than NotFound or NotADirectory. Those two are treated as 'keep searching'; any other IO error (permission denied, I/O error, etc.) is wrapped with anyhow context naming the config file and rethrown as ErrorKind::Other.

Solutions

  1. Check permissions on the directory and the candidate rustfmt.toml path named in the error.
  2. Resolve broken symlinks pointing at the config file.
  3. Retry on a transient filesystem/network-filesystem error.
  4. Move or rename the problematic config file and let rustfmt generate a fresh default.

Example fix

# before: broken symlink at rustfmt.toml
ls -l rustfmt.toml   # lrwxrwxrwx ... -> /nonexistent

# after
rm rustfmt.toml
cp ~/.rustfmt.toml rustfmt.toml
Defensive patterns

Strategy: validation

Validate before calling

fn config_metadata_ok(p: &std::path::Path) -> io::Result<()> {
    match std::fs::metadata(p) {
        Ok(_) => Ok(()),
        Err(e) if matches!(e.kind(), io::ErrorKind::NotFound | io::ErrorKind::NotADirectory) => Ok(()),
        Err(e) => Err(e),
    }
}

Try / catch

match get_toml_path(dir) {
    Ok(p) => Ok(p),
    Err(e) if e.to_string().contains("Failed to get metadata for config file") => {
        // fix permissions / symlink on the named path, then retry
        Err(e)
    }
    Err(e) => Err(e),
}

Prevention

When it happens

Trigger: rustfmt searching a directory for rustfmt.toml/.rustfmt.toml where fs::metadata fails for a non-existence reason - e.g. permission denied on the directory or the candidate path, broken symlink, filesystem I/O error, or a race where the path exists but cannot be stat'd.

Common situations: Config file on a broken symlink; directory not readable due to permissions; network filesystem hiccup; SELinux/AppArmor denying stat; path is a special device that errors on metadata.

Related errors


AI-assisted analysis of rust-lang/rust@7088e4b63a (2026-08-10). Data as JSON: /api/errors/c0c0afa87a84418b. Report an issue: GitHub.

Appendix: source

Thrown at src/tools/rustfmt/src/config/mod.rs:512

// Check for the presence of known config file names (`rustfmt.toml`, `.rustfmt.toml`) in `dir`
//
// Return the path if a config file exists, empty if no file exists, and Error for IO errors
fn get_toml_path(dir: &Path) -> Result<Option<PathBuf>, Error> {
    const CONFIG_FILE_NAMES: [&str; 2] = [".rustfmt.toml", "rustfmt.toml"];
    for config_file_name in &CONFIG_FILE_NAMES {
        let config_file = dir.join(config_file_name);
        match fs::metadata(&config_file) {
            // Only return if it's a file to handle the unlikely situation of a directory named
            // `rustfmt.toml`.
            Ok(ref md) if md.is_file() => return Ok(Some(config_file.canonicalize()?)),
            // We didn't find the project file yet, and continue searching if:
            // `NotFound` => file not found
            // `NotADirectory` => rare case where expected directory is a file
            // Otherwise, return the error
            Err(e) => {
                if !matches!(e.kind(), ErrorKind::NotFound | ErrorKind::NotADirectory) {
                    let ctx = format!("Failed to get metadata for config file {:?}", &config_file);
                    let err = anyhow::Error::new(e).context(ctx);
                    return Err(Error::new(ErrorKind::Other, err));
                }
            }
            _ => {}
        }
    }
    Ok(None)
}

fn config_path(options: &dyn CliOptions) -> Result<Option<PathBuf>, Error> {
    let config_path_not_found = |path: &str| -> Result<Option<PathBuf>, Error> {
        Err(Error::new(
            ErrorKind::NotFound,
            format!(
                "Error: unable to find a config file for the given path: `{}`",
                path
            ),
        ))

View on GitHub (pinned to 7088e4b63a)