GitoxideLabs/gitoxide · error

Required file ' ' does not exist

Error message

Required file '{}' does not exist

What it means

The worktree `Proxy::dot_git()` helper reads the `.git` plain file (a worktree's pointer file containing `gitdir: <path>`). If `<worktree>/.git` cannot be parsed as a plain file, an io::Error with NotFound is returned with this message naming the path.

Solutions

  1. Verify the worktree directory contains a `.git` file (not a directory) pointing at a valid gitdir.
  2. Remove stale worktrees: run `git worktree prune` or `git worktree remove <path>` and skip deleted worktrees.
  3. Check the `.git` file contents start with `gitdir: ` and the target path exists and is readable.

Example fix

// before
let dot_git = wt.proxy().dot_git().expect("worktree valid");

// after
let dot_git_path = wt.path().join(".git");
if !dot_git_path.is_file() {
    eprintln!("skipping stale worktree at {}", wt.path().display());
    continue;
}
Defensive patterns

Strategy: validation

Validate before calling

let git_file = wt.path().join(".git");
if !git_file.is_file() {
    // stale or non-worktree directory: skip
}
if let Ok(text) = std::fs::read_to_string(&git_file) {
    let ok = text.strip_prefix("gitdir: ").map(|t| Path::new(t.trim()).exists()).unwrap_or(false);
}

Type guard

fn is_valid_worktree(path: &Path) -> bool {
    path.join(".git").is_file()
}

Try / catch

match proxy_call() {
    Ok(v) => v,
    Err(e) if e.kind() == std::io::ErrorKind::NotFound => skip_stale_worktree(),
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: Calling methods like `base()` or `is_prunable()` on a linked-worktree proxy when the `<worktree>/.git` file is missing or unreadable (e.g. the worktree was pruned/deleted while its directory remains).

Common situations: Stale linked worktrees whose registration was removed (`git worktree prune`) leaving a dangling directory; manually copied worktree directories without the `.git` pointer file; permission problems making `.git` unreadable.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


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

Appendix: source

Thrown at gix/src/worktree/proxy.rs:49

            git_dir: git_dir.into(),
        }
    }

    pub(crate) fn new_if_gitdir_file_exists(parent: &'repo Repository, git_dir: impl Into<PathBuf>) -> Option<Self> {
        let git_dir = git_dir.into();
        if git_dir.join("gitdir").is_file() {
            Some(Proxy::new(parent, git_dir))
        } else {
            None
        }
    }
}

impl Proxy<'_> {
    fn dot_git(&self) -> std::io::Result<PathBuf> {
        let git_dir = self.git_dir.join("gitdir");
        gix_discover::path::from_plain_file_relative_to_file(&git_dir).ok_or_else(|| {
            std::io::Error::new(
                std::io::ErrorKind::NotFound,
                format!("Required file '{}' does not exist", git_dir.display()),
            )
        })?
    }

    /// Read the location of the checkout, the base of the work tree.
    /// Note that the location might not exist.
    pub fn base(&self) -> std::io::Result<PathBuf> {
        Ok(gix_discover::path::without_dot_git_dir(self.dot_git()?))
    }

    /// The git directory for the work tree, typically contained within the parent git dir.
    pub fn git_dir(&self) -> &Path {
        &self.git_dir
    }

    /// The name of the worktree, which is derived from its folder within the `worktrees` directory within the parent `.git` folder.

View on GitHub (pinned to e73179060b)