gitbutlerapp/gitbutler · error
Cannot currently work in repositories without a worktree
Error message
Cannot currently work in repositories without a worktree
What it means
read_worktree_file() in gitbutler-repo reads a file from the repository's checked-out working tree. gix's Repository::workdir() returns None for bare repositories, and reading workspace files from a bare repo is unsupported, so this error is raised.
Solutions
- Open the repository from a non-bare checkout so workdir() returns Some.
- If you need file contents from a bare repo, read from an object/tree via gix instead of the worktree API.
- Re-clone as a normal working copy and register that path as the project.
Example fix
// before
let repo = gix::open("/srv/origin.git")?; // bare
read_file_from_workspace(&repo, "src/main.rs")?;
// after
let repo = gix::open("~/work/myrepo")?; // non-bare checkout
read_file_from_workspace(&repo, "src/main.rs")?; Defensive patterns
Strategy: validation
Validate before calling
if repo.workdir().is_none() {
return Err(anyhow!("repo is bare; cannot read workspace files"));
} Type guard
fn has_worktree(repo: &gix::Repository) -> bool { repo.workdir().is_some() } Try / catch
match read_file_from_workspace(&repo, path) {
Err(e) if e.to_string().contains("without a worktree") => read_from_tree_fallback(&repo, path),
other => other,
} Prevention
- Check repo.workdir().is_some() before any worktree-file API.
- Open repos from the checkout, not the bare git dir.
- For bare repos, read blobs via tree/object APIs instead.
When it happens
Trigger: Calling get_workspace_file_from_source or read_file_from_workspace (which call read_worktree_file) with a repository handle opened from a bare git dir — e.g. a .git directory opened directly or a bare clone.
Common situations: Tauri commands invoked against a project whose repo was opened from its git dir; pointing GitButler at a bare remote mirror; tests constructing a gix::Repository from a bare path.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Cannot currently work in repositories without a worktree
- Bare repositories are not supported.
- bare repositories are not supported
- `but setup` cannot run from a linked worktree; run it from…
- Cannot hash directory entries that aren't files or symlinks
AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18).
Data as JSON: /api/errors/d405290c6262a60a.
Report an issue: GitHub.
Appendix: source
Thrown at crates/gitbutler-repo/src/commands.rs:364
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(),
})
}
/// Read `path` from the checkout of `repo`, see [`RepoCommands::read_file_from_workspace()`].
/// `path` can be relative or absolute, and is validated to be inside the worktree.
/// A linked worktree opened from disk reads the same way as the main worktree.
pub fn read_worktree_file(repo: &gix::Repository, path: &Path) -> Result<FileInfo> {
let workdir = repo
.workdir()
.ok_or_else(|| anyhow!("Cannot currently work in repositories without a worktree"))?;
let canonical_workdir = gix::path::realpath(workdir)?;
let path = gix::path::realpath(canonical_workdir.join(path))?;
// Double-check that the path is still in the worktree - this might not be the case
// if it was absolute to begin with, or leads through symlinks.
let relative_path = match path.strip_prefix(&canonical_workdir) {
Ok(relative_path) => relative_path.to_owned(),
Err(_) => {
bail!(
"Path to read from at '{}' isn't in the worktree directory '{}'",
path.display(),
canonical_workdir.display()
);
}
};
// Refuse `.git` in every spelling an OS can map onto it (`.GIT`,
// `GIT~1`, `.git.`). Runs before the stat: `.git` can be a file
// (linked worktrees) and must be refused all the same.View on GitHub (pinned to 58e5313667)