gitbutlerapp/gitbutler · error
Cannot operate on uncommitted changes in worktree {name} yet
Error message
Cannot operate on uncommitted changes in worktree {name} yet What it means
Diff specs are built against one checkout's repository, so `push_changes_from_uncommitted` refuses `UncommittedHunkOrFile` values whose `source` differs from the builder's `source`. When the mismatched hunks come from a linked worktree you get this 'yet' message; the operation either needs a builder created for that worktree or does not support worktree sources. (A non-worktree mismatch produces the internal BUG variant instead.)
Source
Thrown at crates/but/src/utils/diff_specs.rs:104
}
CliId::Stack { .. } => {
anyhow::bail!("Cannot compute diff specs for stacks")
}
}
}
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!(
"BUG: a change from {} was pushed into a builder reading {}",
uncommitted.source.describe(),
self.source.describe()
);
}
let hunks = uncommitted.hunks.iter().cloned();
self.push_hunks(hunks.map(|id_and_hunk| id_and_hunk.hunk))
}
pub fn push_changes_from_path_prefix(
&mut self,
hunks: &nonempty::NonEmpty<IdAndHunk>,
) -> anyhow::Result<()> {
self.push_hunks(hunks.iter().map(|id_and_hunk| id_and_hunk.hunk.clone()))
}
View on GitHub (pinned to caf1f223d3)
Solutions
- Construct the builder with `DiffSpecBuilder::for_change_source(...)` using the selection's source so it reads the correct worktree
- Filter the selection so it only contains hunks whose source matches the operation's expected source
- If the operation is intentionally main-worktree-only, reject worktree selections at the UI/CLI boundary before invoking it
Example fix
// before let mut builder = DiffSpecBuilder::new(&main_repo); // reads the main worktree builder.push_changes_from_uncommitted(&hunk_from_worktree)?; // after let mut builder = DiffSpecBuilder::for_change_source(&hunk_from_worktree.source, ...)?; builder.push_changes_from_uncommitted(&hunk_from_worktree)?;
Defensive patterns
Strategy: validation
Validate before calling
// verify sources agree before pushing uncommitted hunks
if uncommitted.source != builder.source {
if let Some(name) = uncommitted.source.worktree_name() {
return Err(anyhow::anyhow!("operation does not support worktree `{name}`"));
}
return Err(anyhow::anyhow!("selection source does not match the builder"));
} Type guard
fn matches_builder_source(uncommitted: &UncommittedHunkOrFile, builder: &DiffSpecBuilder<'_>) -> bool {
uncommitted.source == builder.source
} Try / catch
if let Err(err) = builder.push_changes_from_uncommitted(&uncommitted) {
if err.to_string().contains("worktree") {
let mut builder = DiffSpecBuilder::for_change_source(&uncommitted.source, /* ... */)?;
builder.push_changes_from_uncommitted(&uncommitted)?;
} else {
return Err(err);
}
} Prevention
- Construct builders from the selection's ChangeSource, never from a fixed repository
- Validate selections against the operation's supported sources at the API boundary
When it happens
Trigger: Passing uncommitted hunks captured in worktree `name` into a builder constructed for the main worktree (the default constructor) rather than via `DiffSpecBuilder::for_change_source` with the selection's own source.
Common situations: Multi-worktree projects where selections mix hunks from different checkouts; new operations reusing a main-worktree builder for arbitrary selections; UI flows that forward worktree hunks to main-worktree-only operations.
Related errors
- Cannot compute diff specs for worktree `{name}`
- Invalid token format
- Login token expired. Please log in to GitButler again.
- HTTP Error ${response.statusText}: ${text}
- Cannot compute diff specs for stacks
AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20).
Data as JSON: /api/errors/9bf854c404bcc377.
Report an issue: GitHub.