sharkdp/fd · error · anyhow::Error

A path separator must be exactly one byte, but the given sep

Error message

A path separator must be exactly one byte, but the given separator is {} bytes: '{}'.
In some shells on Windows, '/' is automatically expanded. Try to use '//' instead.

What it means

Thrown by check_path_separator_length in src/main.rs:236. On Windows only, --path-separator must be exactly one byte; a multi-byte value is rejected because MSYS2/Cygwin/Git-Bash auto-expand a lone '/' into a Windows path, and users often try '//' as a workaround that then arrives as a 2-byte string.

Source

Thrown at src/main.rs:236

fn build_pattern_regex(pattern: &str, opts: &Opts) -> Result<String> {
    Ok(if opts.glob && !pattern.is_empty() {
        let glob = GlobBuilder::new(pattern).literal_separator(true).build()?;
        glob.regex().to_owned()
    } else if opts.exact {
        // Anchor the escaped pattern so the full filename (or path) must match exactly.
        // Literal. No substring matching.
        format!("^{}$", regex::escape(pattern))
    } else if opts.fixed_strings {
        // Treat pattern as literal string if '--fixed-strings' is used
        regex::escape(pattern)
    } else {
        String::from(pattern)
    })
}

fn check_path_separator_length(path_separator: Option<&str>) -> Result<()> {
    match (cfg!(windows), path_separator) {
        (true, Some(sep)) if sep.len() > 1 => Err(anyhow!(
            "A path separator must be exactly one byte, but \
                 the given separator is {} bytes: '{}'.\n\
                 In some shells on Windows, '/' is automatically \
                 expanded. Try to use '//' instead.",
            sep.len(),
            sep
        )),
        _ => Ok(()),
    }
}

fn construct_config(mut opts: Opts, pattern_regexps: &[String]) -> Result<Config> {
    // The search will be case-sensitive if the command line flag is set or
    // if any of the patterns has an uppercase character (smart case).
    let case_sensitive = !opts.ignore_case
        && (opts.case_sensitive
            || pattern_regexps
                .iter()

View on GitHub (pinned to 41532d114e)

Solutions

  1. Use a single-byte separator: 'fd --path-separator "/" ...' or a single '\' (note the message's hint about shell expansion).
  2. Quote carefully so the shell does not collapse '/' to a Windows path — in MSYS2 use 'MSYS_NO_PATHCONV=1 fd --path-separator /'.
  3. Omit --path-separator entirely to let fd use the platform default.

Example fix

// before
fd --path-separator "//" .   # on Windows

// after
MSYS_NO_PATHCONV=1 fd --path-separator / .
Defensive patterns

Strategy: validation

Validate before calling

# Windows/MSYS: enforce a single-byte separator and disable path conv
if [ "${#SEP}" -ne 1 ]; then
  echo "--path-separator must be one byte" >&2; exit 1
fi
MSYS_NO_PATHCONV=1 fd --path-separator "$SEP" "$@"

Type guard

fn is_single_byte_sep(s: &str) -> bool {
    s.len() == 1
}

Prevention

When it happens

Trigger: Running 'fd --path-separator "//" ...' on Windows; passing any multi-byte or multi-char separator string under cfg(windows).

Common situations: Coping with POSIX-path output inside a Git-Bash/MSYS2 pipeline; copy-pasting a separator from a shell that already collapsed '/' to a Windows path.

Related errors


AI-assisted analysis of sharkdp/fd@41532d114e (2026-08-06). Data as JSON: /data/errors/75aebac43011389c.json. Report an issue: GitHub.