gitbutlerapp/gitbutler · error

Refusing to read '{relative_path:?}' from commit {commit_id:

Error message

Refusing to read '{relative_path:?}' from commit {commit_id:?} as it's not relative to the worktree

What it means

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.

Source

Thrown at crates/gitbutler-repo/src/commands.rs:281

            let mut section = config.section_mut_or_create_new("remote", Some(name.into()))?;
            section.push("url", Some(url.as_bytes().as_bstr()))?;
            ensure_config_value(
                config,
                &format!("remote.{name}.fetch"),
                &format!("+refs/heads/*:refs/remotes/{name}/*"),
            )?;
            Ok(())
        })?;
        Ok(())
    }

    fn read_file_from_commit(
        &self,
        commit_id: gix::ObjectId,
        relative_path: &Path,
    ) -> Result<FileInfo> {
        if !relative_path.is_relative() {
            bail!(
                "Refusing to read '{relative_path:?}' from commit {commit_id:?} as it's not relative to the worktree"
            );
        }

        let repo = self.repo.get()?;
        let tree = repo.find_commit(commit_id)?.tree()?;

        Ok(match tree.lookup_entry_by_path(relative_path)? {
            Some(entry) => {
                let blob = repo.find_blob(entry.id())?;
                FileInfo::from_content(relative_path, &blob.data)
            }
            None => FileInfo::deleted(),
        })
    }

    /// Note that `path` can be relative or absolute, and we must validate that it's in the worktree.
    fn read_file_from_workspace(&self, path: &Path) -> Result<FileInfo> {

View on GitHub (pinned to caf1f223d3)

Solutions

  1. Strip the worktree prefix before the call: path.strip_prefix(&workdir) yields the repo-relative path the API wants
  2. Normalize separators to '/' and drop leading './' when preparing paths for tree lookups
  3. Validate with Path::is_relative() client-side and reject early with your own error message

Example fix

// before: read_file_from_commit(commit, Path::new("/home/me/repo/src/main.rs"))
// after: pass a worktree-relative path
let rel = absolute.strip_prefix(&workdir)?;
read_file_from_commit(commit, rel)?;
Defensive patterns

Strategy: validation

Validate before calling

if !path.is_relative() {
    let path = path.strip_prefix(&workdir)?; // make it worktree-relative first
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20). Data as JSON: /api/errors/619b5d3776b1bfd5. Report an issue: GitHub.