GitoxideLabs/gitoxide · error · anyhow::Error
history worker stopped unexpectedly
Error message
history worker stopped unexpectedly
What it means
The history worker thread that feeds events over an mpsc channel has terminated before sending all expected events. The main loop detects a disconnected channel while expecting messages and aborts instead of silently producing incomplete history output. This guards against a crashed/panicked worker silently corrupting results.
Solutions
- Check the worker thread for panics or early `?` returns that drop the sender without signalling history_finished.
- Ensure the worker sends a completion/terminal message before dropping the sender.
- Wrap the worker body so errors are forwarded through the channel (`message?` is already handled) instead of returning early.
- Re-run the command; if reproducible, capture a backtrace (RUST_BACKTRACE=1) and report the worker panic.
Example fix
// before
let handle = thread::spawn(move || {
compute_history(tx)?; // early return drops tx silently
});
// after
let handle = thread::spawn(move || {
let result = compute_history(&tx);
let _ = tx.send(Event::Done(result.is_ok()));
result
}); Defensive patterns
Strategy: try-catch
Try / catch
match result {
Err(err) if err.to_string().contains("history worker stopped unexpectedly") => {
// restart the operation or report worker crash
}
other => other?,
} Prevention
- Always send a terminal event before dropping the worker's sender.
- Catch panics in worker threads and forward them over the channel.
- Avoid early `?` returns in worker bodies that skip the completion signal.
When it happens
Trigger: The background history worker thread panicked or returned early (e.g. an internal Err was dropped, thread failed to spawn work) so the sender was dropped while the main loop still expected Event messages via receiver.try_recv().
Common situations: Worker thread panics on malformed repository data; history computation cancelled abnormally; a bug in the worker causing early return before channel closure protocol completes.
Related errors
- time-travel worker stopped unexpectedly
- ' ' is not a valid configuration key
- Cannot use iter_v1() on index of type
- Cannot use iter_v2() on index of type
- BUG: tries to obtain object id from symbolic target
AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08).
Data as JSON: /api/errors/41a778f5f418a224.
Report an issue: GitHub.
Appendix: source
Thrown at gix-tix/src/lib.rs:1737
fill_repository.retain = false;
fill_repository.retained = None;
}
if quit_on_finish
&& quit_inputs.is_empty()
&& matches!(app.state, State::Complete)
&& lane_receiver.is_none()
{
return Ok(app.lane_time);
}
continue;
}
let mut events = 0;
while !history_finished && events < EVENT_BATCH_SIZE {
let message = match receiver.try_recv() {
Ok(message) => message,
Err(mpsc::TryRecvError::Empty) => break,
Err(mpsc::TryRecvError::Disconnected) => {
anyhow::bail!("history worker stopped unexpectedly")
}
};
events += 1;
dirty = true;
match message? {
Event::Decorations(value) => {
app.set_worktree_head((!repository_is_bare).then(|| decoration_head(&value)).flatten(), true);
decorations = value;
}
Event::Commits(rows) => app.extend_commits(rows),
Event::HiddenCommits(rows) => app.extend_hidden_commits(rows),
Event::VisibleComplete => {
if let Some(rows) = app.start_lane_computation() {
lane_receiver = Some(start_lane_worker(rows));
}
}
Event::Complete(graph) => {
history_finished = true;View on GitHub (pinned to e73179060b)