GitoxideLabs/gitoxide · error · anyhow::Error
signature verification worker stopped unexpectedly
Error message
signature verification worker stopped unexpectedly
What it means
Runtime guard in gix-tix's TUI event loop. Signature verification runs on a background worker that sends results over an mpsc channel; when the main loop polls the receiver and finds it disconnected (worker thread panicked or exited without sending results), this error is surfaced because verification can never complete. It indicates a defect in the verification worker rather than a user-input problem — the app cannot recover the lost results. Fix requires diagnosing the worker panic/early exit; restarting the application re-runs verification.
Solutions
- Inspect stderr and any tracing output for the panic that killed the verification worker thread, since the disconnect only reports the symptom
- Update or re-point the reference whose signature verification crashed (e.g. a malformed commit signature) and restart tix so a fresh worker is spawned
- Report the crashing input as a bug if the worker panics reproducibly on a specific commit
Defensive patterns
Strategy: try-catch
When it happens
Trigger: Thrown at gix-tix/src/lib.rs:1500 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08).
Data as JSON: /api/errors/479e45530d09a6ce.
Report an issue: GitHub.
Appendix: source
Thrown at gix-tix/src/lib.rs:1500
if app.changes_suppressed {
app.changes_suppressed = false;
dirty = true;
urgent = true;
} else {
fill_repository.retain = false;
fill_repository.retained = None;
}
}
if let Some(result) = verification_receiver.as_ref().map(mpsc::Receiver::try_recv) {
match result {
Ok(results) => {
app.finish_signature_verification(results);
verification_receiver = None;
dirty = true;
}
Err(mpsc::TryRecvError::Empty) => {}
Err(mpsc::TryRecvError::Disconnected) => {
anyhow::bail!("signature verification worker stopped unexpectedly")
}
}
}
if let Some(result) = lane_receiver.as_ref().map(mpsc::Receiver::try_recv) {
match result {
Ok((rows, graph, lane_time)) => {
let scan =
scan_change_ids(&repository_path, repository_is_bare, change_id_scan_needed(&app), &rows)
.unwrap_or_else(|err| {
tracing::warn!(error = %err, "change ID scan failed");
change_id::Scan::default()
});
app.finish_lane_computation(rows, graph, lane_time);
app.set_change_ids(scan.overrides, scan.duplicates);
ref_tree.set_history_commits(app.rows.iter().map(|row| row.id));
if return_to_history_after_refresh.take().is_some() {
ref_tree.leave();
}View on GitHub (pinned to e73179060b)