{"record":{"id":"c3e9e1fe9252e78d","repo":"GitoxideLabs/gitoxide","slug":"worktrees-parent-dir","errorCode":null,"errorMessage":"worktrees/ parent dir","messagePattern":"worktrees/ parent dir","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gix/src/worktree/proxy.rs","lineNumber":69,"sourceCode":"                format!(\"Required file '{}' does not exist\", git_dir.display()),\n            )\n        })?\n    }\n\n    /// Read the location of the checkout, the base of the work tree.\n    /// Note that the location might not exist.\n    pub fn base(&self) -> std::io::Result<PathBuf> {\n        Ok(gix_discover::path::without_dot_git_dir(self.dot_git()?))\n    }\n\n    /// The git directory for the work tree, typically contained within the parent git dir.\n    pub fn git_dir(&self) -> &Path {\n        &self.git_dir\n    }\n\n    /// The name of the worktree, which is derived from its folder within the `worktrees` directory within the parent `.git` folder.\n    pub fn id(&self) -> &BStr {\n        gix_path::os_str_into_bstr(self.git_dir.file_name().expect(\"worktrees/ parent dir\"))\n            .expect(\"no illformed UTF-8\")\n    }\n\n    /// Return true if the worktree cannot be pruned, moved or deleted, which is useful if it is located on an external storage device.\n    pub fn is_locked(&self) -> bool {\n        self.git_dir.join(\"locked\").symlink_metadata().is_ok()\n    }\n\n    /// Return true if this worktree can be pruned without an expiry grace period.\n    ///\n    /// Locked worktrees are never prunable. Otherwise, an unreadable `gitdir` file or missing target\n    /// makes the worktree prunable.\n    pub fn is_prunable(&self) -> bool {\n        !self.is_locked()\n            && self\n                .dot_git()\n                .map_or(true, |dot_git| dot_git.symlink_metadata().is_err())\n    }","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/GitoxideLabs/gitoxide/blob/e73179060badf27222d790981fac3f84c1830a7e/gix/src/worktree/proxy.rs#L51-L87","documentation":"`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.","triggerScenarios":"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.","commonSituations":"Mounting worktree git dirs at filesystem roots in containers; misconfigured `.git` files pointing `gitdir:` at root-like paths; custom tooling building proxies directly.","solutions":["Verify `proxy.git_dir().file_name().is_some()` before calling `id()` in defensive code.","Recreate the worktree with a normal named directory under `<common-dir>/worktrees/<name>`.","If a standard setup triggers this, file a gitoxide bug with reproduction steps."],"exampleFix":"// before\nlet id = proxy.id(); // may panic\n// after\nlet id = proxy.git_dir().file_name()\n    .map(|n| n.to_string_lossy().into_owned())\n    .unwrap_or_else(|| \"unknown\".into());","handlingStrategy":"validation","validationCode":"if proxy.git_dir().file_name().is_none() {\n    return Err(anyhow::anyhow!(\"worktree git dir has no name component\"));\n}\nlet id = proxy.id();\n","typeGuard":"fn can_derive_id(p: &std::path::Path) -> bool { p.file_name().is_some() }\n","tryCatchPattern":null,"preventionTips":["Ensure linked worktrees live under <common>/worktrees/<name>","Check .git file's gitdir: target points at a named directory","Avoid mounting worktree git dirs at root paths"],"tags":["panic","path","worktree","proxy","git"],"backgroundTag":"internal-invariant-violation","analyzedSha":"e73179060badf27222d790981fac3f84c1830a7e","analyzedAt":"2026-09-08T11:26:50.865Z","contentChangedAt":"2026-09-08T11:26:50.865Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}