sharkdp/fd · error · anyhow::Error

Mismatch in exclude patterns

Error message

Mismatch in exclude patterns

What it means

Thrown by WorkerState::build_overrides in src/walk.rs:344 when OverrideBuilder::build() fails after every individual add() succeeded. The ignore crate's OverrideBuilder can fail at build time when the accumulated set of patterns cannot be compiled together (e.g. mutually contradictory matchers or an internal consistency error).

Source

Thrown at src/walk.rs:344

            interrupt_flag,
        }
    }

    fn build_overrides(&self, paths: &[PathBuf]) -> Result<Override> {
        let first_path = &paths[0];
        let config = &self.config;

        let mut builder = OverrideBuilder::new(first_path);

        for pattern in &config.exclude_patterns {
            builder
                .add(pattern)
                .map_err(|e| anyhow!("Malformed exclude pattern: {}", e))?;
        }

        builder
            .build()
            .map_err(|_| anyhow!("Mismatch in exclude patterns"))
    }

    fn build_walker(&self, paths: &[PathBuf]) -> Result<WalkParallel> {
        let first_path = &paths[0];
        let config = &self.config;
        let overrides = self.build_overrides(paths)?;

        let mut builder = WalkBuilder::new(first_path);
        builder
            .hidden(config.ignore_hidden)
            .ignore(config.read_fdignore)
            .parents(config.read_parent_ignore && (config.read_fdignore || config.read_vcsignore))
            .git_ignore(config.read_vcsignore)
            .git_global(config.read_vcsignore)
            .git_exclude(config.read_vcsignore)
            .require_git(config.require_git_to_read_vcsignore)
            .overrides(overrides)
            .follow_links(config.follow_links)

View on GitHub (pinned to 41532d114e)

Solutions

  1. Reduce the --exclude set to a minimal reproduction and identify the offending pair/pattern.
  2. Re-express conflicting patterns (e.g. consolidate '**/foo' and 'foo' variants into one).
  3. Move complex exclusions into a .fdignore/.gitignore file (which uses a different compilation path) and drop the corresponding --exclude flags.
  4. Check the ignore crate version/changelog if a previously working pattern set started failing after a dependency bump.

Example fix

// before
fd --exclude 'foo/**' --exclude 'foo' bar

// after
fd --exclude 'foo' bar
Defensive patterns

Strategy: validation

Validate before calling

# in automation, keep --exclude sets small and internally consistent
if [ "${#EXCLUDES[@]}" -gt 16 ]; then
  echo "too many --exclude patterns; move them to .fdignore" >&2; exit 1
fi
fd "${EXCLUDES[@]/#/--exclude }" "$PAT"

Type guard

use ignore::overrides::OverrideBuilder;
fn exclude_set_builds(base: &str, pats: &[&str]) -> bool {
    let mut b = OverrideBuilder::new(base);
    pats.iter().all(|p| b.add(p).is_ok()) && b.build().is_ok()
}

Prevention

When it happens

Trigger: Combining several --exclude patterns whose union the ignore crate cannot compile into a single matcher; extremely large or pathological pattern sets; rare internal inconsistency after all adds passed.

Common situations: A long list of --exclude flags generated from a script producing a contradictory set; version differences in the ignore crate's glob compiler rejecting an edge case only at build time.

Related errors


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