gitbutlerapp/gitbutler · critical
diffing-thread crashed
Error message
diffing-thread crashed
What it means
Branch listing details offload per-file line counting to a dedicated `gitbutler-diff-stats` thread fed over mpsc channels. The bail fires when `start.send(...)` fails, which can only happen once the receiving channel end in that thread was dropped — i.e. the diff-stats thread already exited, either because its initialization (`for_tree_diffing` / `diff_resource_cache_for_tree_diff`) failed or it panicked. The error therefore points at an earlier crash in the background worker, not at the send itself.
Source
Thrown at crates/gitbutler-branch-actions/src/branch.rs:843
}
Ok(())
}
})?;
for branch in branches {
let Some((base, authors, num_commits)) = merge_rx.recv()? else {
continue;
};
let branch_head = branch.head;
let base_commit = repo.find_object(base)?.try_into_commit()?;
let base_tree = base_commit.tree()?;
let head_tree = repo.find_object(branch_head)?.peel_to_tree()?;
let ((change_tx, change_rx), (res_tx, rex_rx)) =
(std::sync::mpsc::channel(), std::sync::mpsc::channel());
if start.send((change_rx, res_tx)).is_err() {
bail!("diffing-thread crashed");
};
base_tree
.changes()?
.options(|opts| {
opts.track_rewrites(None);
})
// NOTE: `stats(head_tree)` is also possible, but we have a separate thread for that.
.for_each_to_obtain_tree(&head_tree, move |change| -> anyhow::Result<Action> {
change_tx.send(change.detach()).ok();
Ok(std::ops::ControlFlow::Continue(()))
})?;
let (number_of_files, lines_added, lines_removed) = rex_rx.recv()?;
let branch_data = BranchListingDetails {
name: branch.name,
lines_added,
lines_removed,
number_of_files,View on GitHub (pinned to caf1f223d3)
Solutions
- Check application logs for a panic or error from the `gitbutler-diff-stats` thread — that is the real failure
- Run `git fsck` in the affected repository to rule out object database corruption
- Restart the app and retry; a transient init failure usually clears
- If it reproduces deterministically, capture the backtrace and report it as a GitButler bug
Defensive patterns
Strategy: retry
Try / catch
match list_branch_listing_details(ctx) {
Ok(details) => { /* continue */ }
Err(err) if err.to_string().contains("diffing-thread crashed") => {
// the gitbutler-diff-stats worker died; check its panic log, restart, retry once
}
Err(err) => return Err(err),
} Prevention
- Treat this error as a symptom: always pull the panic log from the gitbutler-diff-stats thread
- Run `git fsck` on repositories that hit it repeatedly to rule out object corruption
- Avoid running `git gc --prune` concurrently with GitButler operations
When it happens
Trigger: Calling the branch listing API while the `gitbutler-diff-stats` thread dies at startup (repository state its gix calls reject) or panics while handling a previous branch's diff, so subsequent `start.send` for the next branch fails.
Common situations: Corrupted packfiles or object database; repository mutated concurrently (git gc/prune, another Git client) while stats were computed; a GitButler bug panicking inside the diff-stats loop.
Related errors
- Failed to communicate with LM Studio server: ${error instanc
- Invalid response: ${JSON.stringify(result)}
- When using GitButler's API to summarize code, you must be lo
- When using LM Studio, you must provide a valid endpoint
- When using OpenAI in a bring your own key configuration, you
AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20).
Data as JSON: /api/errors/6caa1d83b5725fd4.
Report an issue: GitHub.