GitoxideLabs/gitoxide · error

path does not name a file

Error message

path {display:?} does not name a file

What it means

`gix_tix::command::resolve_spill_paths` normalizes each user-supplied path argument to a repository-relative Git path. If the normalized path is empty — meaning the argument referred to the repository root or degenerated to nothing — it bails, because spilling requires a path that actually names a file within the change set.

Solutions

  1. Pass explicit file paths that exist in the change set instead of the repository root or `.`.
  2. Verify each argument names a file touched by the current changes (check the todo/changes view).
  3. Run the command from the repository root with repo-relative paths.
  4. Guard scripts to filter out directory/root arguments before invoking spill.

Example fix

// before
gix tix spill .
// after
gix tix spill src/main.rs src/lib.rs
Defensive patterns

Strategy: validation

Validate before calling

// Before calling spill: ensure every argument normalizes to a non-empty repo-relative file path.
let norm = repo.normalize_path(git_path(arg))?;
if norm.is_empty() { skip_or_error(arg); }

Type guard

fn is_named_file_path(p: &BString) -> bool { !p.is_empty() }

Try / catch

match run_spill(repo, paths) { Err(e) if e.to_string().starts_with("path ") && e.to_string().contains("does not name a file") => { /* drop root/dir args and retry */ } other => other }

Prevention

When it happens

Trigger: Passing `/`, `.` or the worktree root as a path argument to the spill command so `repository.normalize_path` yields an empty path; `changes.paths` then has no usable per-file entry for it.

Common situations: Shell globs expanding to the repo root; copy-pasting a directory or root path where a file path is required; running the command from an odd working directory so a relative path normalizes to 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/53ceed87d0d07879. Report an issue: GitHub.

Appendix: source

Thrown at gix-tix/src/command.rs:662

                .context("could not load HEAD's first parent")?
                .tree()
                .context("could not load HEAD's first-parent tree")?,
        ),
        None => None,
    };
    let changes = crate::load_tree_changes_without_lines(repository, old_tree.as_ref(), &new_tree, None)?;
    let mut seen = HashSet::new();
    let mut selected = Vec::with_capacity(paths.len());
    for path in paths {
        let display = path.to_string_lossy();
        let path = gix::path::os_str_into_bstr(path)
            .with_context(|| format!("path {display:?} could not be converted to a Git path"))?;
        let path = repository
            .normalize_path(path)
            .with_context(|| format!("could not normalize path {display:?}"))?
            .into_owned();
        if path.is_empty() {
            anyhow::bail!("path {display:?} does not name a file");
        }
        if !seen.insert(path.clone()) {
            continue;
        }
        let change = changes
            .paths
            .iter()
            .find(|change| change.path == path)
            .with_context(|| format!("path {display:?} is not changed by HEAD"))?;
        selected.push(change.clone());
    }
    Ok(Some(selected))
}

fn split(repository: gix::Repository, graph: &crate::history::HistoryGraph, args: Split) -> Result<()> {
    let repository_path = repository.git_dir().to_owned();
    let bare = repository.is_bare();
    let mut prepared = crate::edit::split::prepare(repository, args.todo)?;

View on GitHub (pinned to e73179060b)