gitbutlerapp/gitbutler · error
Cannot compute diff specs for stacks
Error message
Cannot compute diff specs for stacks
What it means
Unsupported-kind guard in the diff-spec builder's push_changes_from_id: a stack CliId was passed, but diff specs can only be computed for concrete change sources (commits, uncommitted areas, hunks), not whole stacks. The caller must expand or narrow the selection to supported ID kinds.
Solutions
- Pass a specific commit, hunk, or file id within the stack instead of the stack id
- List the stack's commits first (e.g. `but log <stack>`) and choose a concrete id
- Use a command designed for stack-level operations if a whole-stack action is intended
Example fix
// before but <op> my-stack # stack id -> error // after but <op> abc123f # a commit id inside the stack
Defensive patterns
Strategy: validation
Validate before calling
if matches!(id, CliId::Stack{..}) {
eprintln!("stack ids cannot build diff specs; pick a commit inside the stack");
return Ok(());
} Type guard
fn is_stack_id(id: &CliId) -> bool { matches!(id, CliId::Stack{..}) } Try / catch
if let Err(e) = cmd() { if e.to_string().contains("for stacks") { /* fall back to per-commit ids */ } else { return Err(e); } } Prevention
- Resolve stacks to their commits before issuing per-change commands
- Distinguish stack ids from commit ids in `but status` output
- Reject stack ids early in automation pipelines
When it happens
Trigger: Passing a `CliId::Stack` id (e.g. a stack name shown in `but status`) to a command whose id handling goes through `push_changes_from_id`.
Common situations: Using the stack name from `but status` output where a commit, hunk, or file id is expected; automation that iterates stacks and feeds stack ids into per-change commands.
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 compute diff specs for branch
- Cannot compute diff specs for committed hunks
- Cannot compute diff specs for worktree
- Could not find stack containing commit
- Could not resolve stack
AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18).
Data as JSON: /api/errors/facb08ba2d01e0d1.
Report an issue: GitHub.
Appendix: source
Thrown at crates/but/src/utils/diff_specs.rs:93
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 refuse
// worktree hunks here.
if uncommitted.source != self.source {
if let Some(name) = uncommitted.source.worktree_name() {View on GitHub (pinned to 58e5313667)