sharkdp/fd · error · anyhow::Error

The '--base-directory' path

Error message

The '--base-directory' path '{}' is not a directory.

What it means

set_working_dir (main.rs:131) runs before any search and validates that --base-directory points to an existing directory via filesystem::is_existing_directory. If the path is missing, a file, or inaccessible, fd refuses to chdir into it rather than failing later with a noisier syscall error.

Solutions

  1. Verify the path exists and is a directory: `ls -ld <path>`.
  2. Use an absolute path to avoid cwd-relative resolution surprises.
  3. Fix permissions if the directory exists but is unreadable.

Example fix

# before
fd --base-directory /srcc .

# after
fd --base-directory /home/user/src .
Defensive patterns

Strategy: validation

Validate before calling

validate_base_dir() {
  local d="$1"
  if [ -d "$d" ]; then
    fd --base-directory "$d" .
  else
    echo "$d is not a directory" >&2; exit 1
  fi
}

Prevention

When it happens

Trigger: Passing `fd --base-directory /nonexistent`, pointing it at a regular file (`fd --base-directory ./file.txt`), or a path on an unmounted/removable drive. The check runs on every invocation that sets --base-directory.

Common situations: Typo in the path; relative path resolved against an unexpected cwd; deleted/moved directories; symlinks to nonexistent targets; permission errors that make is_existing_directory return false.

Related errors


AI-assisted analysis of sharkdp/fd@ee20f426dd (2026-08-09). Data as JSON: /api/errors/d837eb09f2bd749c. Report an issue: GitHub.

Appendix: source

Thrown at src/main.rs:134

fn print_completions(shell: clap_complete::Shell) -> Result<ExitCode> {
    // The program name is the first argument.
    let first_arg = env::args().next();
    let program_name = first_arg
        .as_ref()
        .map(Path::new)
        .and_then(|path| path.file_stem())
        .and_then(|file| file.to_str())
        .unwrap_or("fd");
    let mut cmd = Opts::command();
    cmd.build();
    clap_complete::generate(shell, &mut cmd, program_name, &mut std::io::stdout());
    Ok(ExitCode::Success)
}

fn set_working_dir(opts: &Opts) -> Result<()> {
    if let Some(ref base_directory) = opts.base_directory {
        if !filesystem::is_existing_directory(base_directory) {
            return Err(anyhow!(
                "The '--base-directory' path '{}' is not a directory.",
                base_directory.to_string_lossy()
            ));
        }
        env::set_current_dir(base_directory).with_context(|| {
            format!(
                "Could not set '{}' as the current working directory",
                base_directory.to_string_lossy()
            )
        })?;
    }
    Ok(())
}

/// Detect if the user accidentally supplied a path instead of a search pattern.
///
/// Without `--full-path`, fd matches patterns against file names, so any pattern
/// containing a path separator can never match. This applies to the primary

View on GitHub (pinned to ee20f426dd)