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.

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)

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.