GitoxideLabs/gitoxide · error

worktrees/ parent dir

Error message

worktrees/ parent dir

What it means

`gix::worktree::Proxy::id()` derives the worktree name from `self.git_dir.file_name()` and expects it to exist because the proxy is normally only created for git dirs under a `worktrees/` parent. If the proxy was built for a git dir without a final path component (root path) the expect panics. Public API, so any caller holding a proxy for such a git dir sees the panic.

Solutions

  1. Verify `proxy.git_dir().file_name().is_some()` before calling `id()` in defensive code.
  2. Recreate the worktree with a normal named directory under `<common-dir>/worktrees/<name>`.
  3. If a standard setup triggers this, file a gitoxide bug with reproduction steps.

Example fix

// before
let id = proxy.id(); // may panic
// after
let id = proxy.git_dir().file_name()
    .map(|n| n.to_string_lossy().into_owned())
    .unwrap_or_else(|| "unknown".into());
Defensive patterns

Strategy: validation

Validate before calling

if proxy.git_dir().file_name().is_none() {
    return Err(anyhow::anyhow!("worktree git dir has no name component"));
}
let id = proxy.id();

Type guard

fn can_derive_id(p: &std::path::Path) -> bool { p.file_name().is_some() }

Prevention

When it happens

Trigger: Constructing/obtaining a `worktree::Proxy` whose `git_dir` is `/` or otherwise component-less, then calling `.id()`; also reachable if repo open logic misidentifies a linked worktree.

Common situations: Mounting worktree git dirs at filesystem roots in containers; misconfigured `.git` files pointing `gitdir:` at root-like paths; custom tooling building proxies directly.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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

Appendix: source

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

                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.
    pub fn id(&self) -> &BStr {
        gix_path::os_str_into_bstr(self.git_dir.file_name().expect("worktrees/ parent dir"))
            .expect("no illformed UTF-8")
    }

    /// Return true if the worktree cannot be pruned, moved or deleted, which is useful if it is located on an external storage device.
    pub fn is_locked(&self) -> bool {
        self.git_dir.join("locked").symlink_metadata().is_ok()
    }

    /// Return true if this worktree can be pruned without an expiry grace period.
    ///
    /// Locked worktrees are never prunable. Otherwise, an unreadable `gitdir` file or missing target
    /// makes the worktree prunable.
    pub fn is_prunable(&self) -> bool {
        !self.is_locked()
            && self
                .dot_git()
                .map_or(true, |dot_git| dot_git.symlink_metadata().is_err())
    }

View on GitHub (pinned to e73179060b)