gitbutlerapp/gitbutler · error
Cannot compute diff specs for worktree
Error message
Cannot compute diff specs for worktree `{name}` What it means
Diff specs cannot be computed for a whole worktree or its uncommitted area: during id resolution a worktree's uncommitted area is already expanded into its individual files, and the worktree reference itself holds no changes. The builder therefore rejects both `CliId::Worktree` and `CliId::WorktreeUncommitted` ids.
Solutions
- Use ids of the worktree's individual files/hunks instead of the worktree id
- If worktree-source support is needed, construct the builder with `for_change_source` rather than the default main-worktree builder
- Operate from inside the worktree so its changes appear as the normal uncommitted area
Defensive patterns
Strategy: validation
Validate before calling
if matches!(id, CliId::Worktree{..} | CliId::WorktreeUncommitted{..}) {
eprintln!("worktree ids are not a diff-spec source; use its file/hunk ids");
return Ok(());
} Type guard
fn is_worktree_id(id: &CliId) -> bool { matches!(id, CliId::Worktree{..} | CliId::WorktreeUncommitted{..}) } Try / catch
match result { Err(e) if e.to_string().starts_with("Cannot compute diff specs for worktree") => { /* use file ids from the worktree */ }, other => other } Prevention
- Expand worktrees into their file/hunk ids before building diffs
- Use `for_change_source` when an operation must support worktree sources
- Run commands inside the worktree to address its changes directly
When it happens
Trigger: Passing a worktree id or worktree-uncommitted id to an operation that calls `push_changes_from_id`; per the source comment, operations that do support worktree sources must construct the builder via `DiffSpecsBuilder::for_change_source` instead.
Common situations: Targeting a linked worktree with a command that only reads the main worktree; scripting against `but worktree`/status output and using the worktree id where a file or hunk id is required.
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
- `but setup` cannot run from a linked worktree; run it from…
- Cannot compute diff specs for branch
- Cannot compute diff specs for committed hunks
- Cannot compute diff specs for stacks
- Cannot operate on uncommitted changes in worktree
AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18).
Data as JSON: /api/errors/4c4ca45298347785.
Report an issue: GitHub.
Appendix: source
Thrown at crates/but/src/utils/diff_specs.rs:90
anyhow::bail!("Cannot compute diff specs for branch `{}`", branch.name)
}
CliId::AnonymousSegment(segment) => {
anyhow::bail!("{}", anonymous_segment_error(&segment.id))
}
CliId::Commit {
commit:
CommitId {
commit_id,
change_id: _,
},
id: _,
} => self.push_changes_from_commit(*commit_id),
CliId::Uncommitted { id: _ } => self.push_changes_from_uncommitted_area(),
// A worktree's uncommitted area is expanded into its files during
// resolution, so the builder only ever sees hunks that already come from
// its own repo. The reference holds no changes at all.
CliId::Worktree { name, .. } | CliId::WorktreeUncommitted { name, .. } => {
anyhow::bail!("Cannot compute diff specs for worktree `{name}`")
}
CliId::Stack { .. } => {
anyhow::bail!("Cannot compute diff specs for stacks")
}
CliId::CommittedHunk(_) => {
anyhow::bail!("Cannot compute diff specs for committed hunks")
}
}
}
pub fn push_changes_from_uncommitted(
&mut self,
uncommitted: &UncommittedHunkOrFile,
) -> anyhow::Result<()> {
// Specs are built against one checkout's repository, so a hunk from
// another would silently address the wrong files. Operations that support
// worktree sources validate the selection and construct the builder via
// [`Self::for_change_source`]; the rest read the main worktree and refuseView on GitHub (pinned to 58e5313667)