gitbutlerapp/gitbutler · error
BUG: this must have been deactivated
Error message
BUG: this must have been deactivated
What it means
When `create_tree` snapshots the index into the snapshot tree (but-core/src/snapshot/create_tree.rs), `Change::Rewrite` from the tree↔index diff is `unreachable!` because that diff is created with rewrite detection deactivated, so the index diff only emits plain modifications/additions/deletions. The panic indicates the diff producing these changes was built with rename/copy rewrites enabled, breaking the snapshot builder's assumption.
Source
Thrown at crates/but-core/src/snapshot/create_tree.rs:239
..
}
| Change::Modification {
location,
entry_mode,
id,
..
} => {
base_tree_edit.upsert(
location.as_bstr(),
entry_mode
.to_tree_entry_mode()
.with_context(|| format!("Could not convert the index entry {entry_mode:?} at '{location}' into a tree entry kind"))?
.kind(),
id.into_owned(),
)?;
}
Change::Rewrite { .. } => {
unreachable!("BUG: this must have been deactivated")
}
}
}
let index = base_tree_edit.write()?;
let index = (index != base_tree.id).then_some(index.detach());
if let Some(index) = index {
snapshot_tree.upsert("index", EntryKind::Tree, index)?;
}
let index_conflicts = if conflicts.is_empty() {
None
} else {
let mut root = snapshot_tree.cursor_at("index-conflicts")?;
for (rela_path, conflict_entries) in conflicts {
for (stage, entry) in conflict_entries
.into_iter()
.enumerate()View on GitHub (pinned to caf1f223d3)
Solutions
- Create the diff for snapshot tree building with rewrite detection `None`.
- Keep rename-aware diffs in a separate platform instance consumed only by display code.
- Regression-test snapshot creation after any change to shared diff options.
Example fix
// before
let changes = repo.diff_tree_to_index(base_tree, None, gix::diff::tree::Options {
rewrites: Some(gix::diff::Rewrites::default()),
..Default::default()
})?; // Rewrite changes reach create_tree
// after
let changes = repo.diff_tree_to_index(base_tree, None, gix::diff::tree::Options {
rewrites: None, // snapshot path expects no Rewrite variants
..Default::default()
})?; Defensive patterns
Strategy: validation
Validate before calling
// snapshot tree building requires a rewrite-free tree-to-index diff
let changes = repo.diff_tree_to_index(
base_tree,
None,
gix::diff::tree::Options { rewrites: None, ..Default::default() },
)?; Prevention
- Set rewrites to None on every diff whose changes flow into snapshot tree creation.
- Keep rename-aware diffs confined to display/UI pipelines.
- Re-run snapshot tests whenever diff options are centralized or gix is upgraded.
When it happens
Trigger: Constructing the tree↔index diff with `gix::diff::Rewrites` enabled and passing its changes into the snapshot tree builder; option plumbing changes that share a rewrite-enabled platform with snapshot creation; gix version default changes.
Common situations: Reusing one diff platform configured for rename-aware UI across snapshot code; refactors that centralize diff options; dependency upgrades.
Related errors
- disabled
- we never return these as the status iteration is configured
- BUG: we use 'matching' so there are no directories
- BUG: `gix` disables this, as it knows we always need to be a
- worktree-changes are always set if there are hunks
AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20).
Data as JSON: /api/errors/6ac219e311c4dddc.
Report an issue: GitHub.