gitbutlerapp/gitbutler · error
Cannot compute diff specs for committed hunks
Error message
Cannot compute diff specs for committed hunks
What it means
Unsupported-kind guard in push_changes_from_id: a committed-hunk CliId was passed. Hunks from commits are not addressable as diff-spec sources — the builder only handles commits, uncommitted areas, and worktree/file-level IDs — so the caller must reference the commit or file instead of a committed hunk.
Solutions
- Use the commit id or file path containing the hunk instead of the committed-hunk id
- If partial staging of a committed hunk is intended, use a command that explicitly supports committed-hunk operations
- Re-check `but status` output: uncommitted hunk ids may be what the command actually accepts
Defensive patterns
Strategy: validation
Validate before calling
if matches!(id, CliId::CommittedHunk(_)) {
eprintln!("committed hunk ids are not accepted here; use the commit or file id");
return Ok(());
} Type guard
fn is_committed_hunk(id: &CliId) -> bool { matches!(id, CliId::CommittedHunk(_)) } Try / catch
if let Err(e) = cmd() { if e.to_string().contains("committed hunks") { /* retry with parent commit id */ } else { return Err(e); } } Prevention
- Use commit or file ids for already-committed changes
- Only use hunk ids for uncommitted changes unless the command documents hunk support
- Check the command's accepted id kinds before scripting
When it happens
Trigger: Passing a committed-hunk id to a command that resolves ids through `push_changes_from_id`; the operation does not support diffing individual hunks already committed.
Common situations: Copying a hunk id from `but show`/log output of a committed change and using it with a command that only accepts whole commits, files, or uncommitted hunks.
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 stacks
- Cannot compute diff specs for worktree
- {}
- No diffs to show.
AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18).
Data as JSON: /api/errors/cdd2daaae5c80163.
Report an issue: GitHub.
Appendix: source
Thrown at crates/but/src/utils/diff_specs.rs:96
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() {
anyhow::bail!("Cannot operate on uncommitted changes in worktree {name} yet");
}
anyhow::bail!(View on GitHub (pinned to 58e5313667)