{"record":{"id":"619b5d3776b1bfd5","repo":"gitbutlerapp/gitbutler","slug":"refusing-to-read-relative-path-from-commit","errorCode":null,"errorMessage":"Refusing to read '{relative_path:?}' from commit {commit_id:?} as it's not relative to the worktree","messagePattern":"Refusing to read '(.+?)' from commit (.+?) as it's not relative to the worktree","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/gitbutler-repo/src/commands.rs","lineNumber":281,"sourceCode":"            let mut section = config.section_mut_or_create_new(\"remote\", Some(name.into()))?;\n            section.push(\"url\", Some(url.as_bytes().as_bstr()))?;\n            ensure_config_value(\n                config,\n                &format!(\"remote.{name}.fetch\"),\n                &format!(\"+refs/heads/*:refs/remotes/{name}/*\"),\n            )?;\n            Ok(())\n        })?;\n        Ok(())\n    }\n\n    fn read_file_from_commit(\n        &self,\n        commit_id: gix::ObjectId,\n        relative_path: &Path,\n    ) -> Result<FileInfo> {\n        if !relative_path.is_relative() {\n            bail!(\n                \"Refusing to read '{relative_path:?}' from commit {commit_id:?} as it's not relative to the worktree\"\n            );\n        }\n\n        let repo = self.repo.get()?;\n        let tree = repo.find_commit(commit_id)?.tree()?;\n\n        Ok(match tree.lookup_entry_by_path(relative_path)? {\n            Some(entry) => {\n                let blob = repo.find_blob(entry.id())?;\n                FileInfo::from_content(relative_path, &blob.data)\n            }\n            None => FileInfo::deleted(),\n        })\n    }\n\n    /// Note that `path` can be relative or absolute, and we must validate that it's in the worktree.\n    fn read_file_from_workspace(&self, path: &Path) -> Result<FileInfo> {","sourceCodeStart":263,"sourceCodeEnd":299,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/gitbutler-repo/src/commands.rs#L263-L299","documentation":"Thrown by read_file_from_commit when the requested path is not relative. The API reads a file out of a commit's tree, and tree lookups only make sense for worktree-relative paths, so an absolute path ('/etc/passwd', 'C:\\repo\\file') is rejected up front via relative_path.is_relative(). It is a precondition/security check, not a filesystem error.","triggerScenarios":"Calling read_file_from_commit(commit_id, relative_path) where the path starts with '/' (Unix) or a drive/UNC prefix (Windows), so is_relative() returns false and the function bails before opening the repo or looking up the tree.","commonSituations":"Frontends or scripts building paths from OS file dialogs (which return absolute paths) and passing them through unchanged; porting code from an API that accepted absolute paths and silently rooted them at the repo; Windows callers passing backslashed absolute paths.","solutions":["Strip the worktree prefix before the call: path.strip_prefix(&workdir) yields the repo-relative path the API wants","Normalize separators to '/' and drop leading './' when preparing paths for tree lookups","Validate with Path::is_relative() client-side and reject early with your own error message"],"exampleFix":"// before: read_file_from_commit(commit, Path::new(\"/home/me/repo/src/main.rs\"))\n// after: pass a worktree-relative path\nlet rel = absolute.strip_prefix(&workdir)?;\nread_file_from_commit(commit, rel)?;","handlingStrategy":"validation","validationCode":"if !path.is_relative() {\n    let path = path.strip_prefix(&workdir)?; // make it worktree-relative first\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always derive paths via strip_prefix from the worktree root","Never feed OS-dialog absolute paths into file-by-commit APIs","Normalize separators before tree lookups"],"tags":["git","path-validation","precondition","security"],"backgroundTag":"absolute-path-rejected","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}