{"record":{"id":"4278c04ea8247c27","repo":"gitbutlerapp/gitbutler","slug":"failed-to-resolve-path-to-hunk","errorCode":null,"errorMessage":"Failed to resolve path to hunk","messagePattern":"Failed to resolve path to hunk","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/but/src/command/open.rs","lineNumber":53,"sourceCode":"\n#[derive(Debug)]\npub(crate) enum Openable {\n    File(PathBuf),\n    Files(NonEmpty<PathBuf>),\n    Hunk(Hunk),\n}\n\nimpl Openable {\n    /// Try to create an [`Openable`] from an [`UncommittedHunkOrFile`].\n    pub fn try_from_uncommitted(\n        repo: &gix::Repository,\n        uncommitted: &UncommittedHunkOrFile,\n    ) -> anyhow::Result<Self> {\n        let hunk = &uncommitted.hunks.first().hunk;\n\n        let path = repo\n            .workdir_path(hunk.path.as_bstr())\n            .ok_or_else(|| anyhow::anyhow!(\"Failed to resolve path to hunk\"))?;\n\n        let openable = match (\n            uncommitted.is_entire_file,\n            &hunk.hunk_header,\n            hunk.line_nums(),\n        ) {\n            (false, Some(hunk_header), Some((line_nums_added, line_nums_removed))) => {\n                Openable::Hunk(Hunk {\n                    // Truncate line numbers - the probability of exceeding a u32 is infinitesimally small.\n                    line_nums_added: line_nums_added\n                        .iter()\n                        .map(|n| (*n).min(u32::MAX as usize) as u32)\n                        .collect(),\n                    line_nums_removed: line_nums_removed\n                        .iter()\n                        .map(|n| (*n).min(u32::MAX as usize) as u32)\n                        .collect(),\n                    old_start: hunk_header.old_start,","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/but/src/command/open.rs#L35-L71","documentation":"`but open` maps a selected uncommitted hunk to a file/line location via repo.workdir_path(hunk.path). That helper returns None when the repository has no working directory, so the hunk's repository-relative path cannot be made absolute and opening is refused.","triggerScenarios":"Invoking `but open` (or Openable::try_from_uncommitted) on an uncommitted hunk while the opened repository is bare, typically because but was started from a bare clone or from the gitdir side of a linked worktree.","commonSituations":"Running the TUI from a .git directory or worktree admin dir; the worktree was removed or moved while a TUI session was still open.","solutions":["Restart but from the directory containing the working copy (`git rev-parse --show-toplevel` shows it)","Confirm the repo is not bare: `git rev-parse --is-bare-repository` must print false","If the worktree moved, restart the session so hunk paths are re-resolved"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"let repo = ctx.repo.get()?;\nanyhow::ensure!(\n    repo.workdir().is_some(),\n    \"cannot open hunks without a working directory\"\n);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Run but from the worktree root, never from .git or a bare clone","Restart the session after moving or removing worktrees"],"tags":["open","hunk","workdir","bare-repository"],"backgroundTag":"bare-repository-no-worktree","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}