GitoxideLabs/gitoxide · error

Invalid pathspec - path must not be empty, not be excluded…

Error message

Invalid pathspec {spec} - path must not be empty, not be excluded, and wildcards are taken literally

What it means

Thrown by the repository query engine (`gitoxide_core::query::engine::command::run`) when a pathspec is invalid: the normalized path relative to the repository is empty, or the path is excluded, or it contains wildcards (which are treated literally here). The error includes the offending spec so the user can correct it.

Solutions

  1. Provide a concrete, non-empty path relative to the repository root instead of `.` or an excluded path
  2. Remove wildcard characters - paths are matched literally
  3. Verify the path is not covered by exclusion patterns in the query configuration
  4. Escape or restructure paths containing `*`, `?`, or `[` characters

Example fix

// before
gix repo query --pathspec "src/*.rs"
// after
# wildcards are literal; list concrete paths instead
gix repo query --pathspec "src/main.rs" --pathspec "src/lib.rs"
Defensive patterns

Strategy: validation

Try / catch

if let Err(e) = run(/* args */) {
    if e.to_string().starts_with("Invalid pathspec") {
        eprintln!("pathspec rejected: {e}");
    }
}

Prevention

When it happens

Trigger: Invoking a query command with a pathspec that (a) normalizes to an empty relative path (e.g. the repo root itself), (b) points to an excluded path (matched by exclusion patterns), or (c) contains glob characters like `*` that this engine does not expand.

Common situations: Passing `.` or the repository root as a path; pathspec matching an ignored/excluded file; using shell-style wildcards like `src/*.rs` expecting glob behavior; scripts constructing pathspecs from variables that end up empty.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08). Data as JSON: /api/errors/a4046f863dfd70d1. Report an issue: GitHub.

Appendix: source

Thrown at gitoxide-core/src/query/engine/command.rs:32

        &self,
        cmd: Command,
        mut out: impl std::io::Write,
        mut progress: impl gix::NestedProgress,
    ) -> anyhow::Result<()> {
        match cmd {
            Command::TracePath { spec } => {
                let is_excluded = spec.is_excluded();
                let relpath = if spec.signature.contains(gix::pathspec::MagicSignature::TOP) {
                    let root = self.repo.workdir().unwrap_or_else(|| self.repo.git_dir());
                    let path = root.join(gix::path::from_bstr(spec.path()).as_ref());
                    self.repo
                        .normalize_path(gix::path::into_bstr(path).as_ref())?
                        .into_owned()
                } else {
                    self.repo.normalize_path(spec.path())?.into_owned()
                };
                if relpath.is_empty() || is_excluded {
                    bail!(
                        "Invalid pathspec {spec} - path must not be empty, not be excluded, and wildcards are taken literally"
                    )
                }
                let file_id: usize = self
                    .con
                    .query_row(
                        "SELECT file_id FROM files WHERE file_path = ?",
                        params![relpath.to_str_lossy()],
                        |r| r.get(0),
                    )
                    .optional()?
                    .with_context(|| format!("Path '{relpath}' not found anywhere in recorded history"))?;

                let mut by_file_id = self
                    .con
                    .prepare("SELECT hash, mode, source_file_id, has_diff, lines_added, lines_removed from commit_file where file_id = ? order by mode")?;
                let mut path_by_id = self.con.prepare("SELECT file_path from files where file_id = ?")?;
                let mut seen = HashMap::<usize, String>::new();

View on GitHub (pinned to e73179060b)