GitoxideLabs/gitoxide · error
time-travel worker panicked
Error message
time-travel worker panicked
What it means
After the time-travel animation finishes, the main thread calls `worker.join()`; if the JoinHandle returns `Err` (the worker thread panicked), the animation wrapper converts it to this error instead of propagating the panic payload.
Solutions
- Find the underlying panic: capture the JoinError payload (`err.into_panic()`) and downcast to `&str`/`String` to log the real message and backtrace.
- Fix the panicking code in the worker (replace unwraps with error propagation).
- Optionally run the worker body under `std::panic::catch_unwind` and report the panic as a normal error event over the channel.
Example fix
// before
if worker.join().is_err() {
return Err(anyhow::anyhow!("time-travel worker panicked"));
}
// after
if let Err(join_err) = worker.join() {
let msg = join_err.downcast_ref::<String>().cloned()
.or_else(|| join_err.downcast_ref::<&str>().map(|s| s.to_string()))
.unwrap_or_else(|| "unknown panic".into());
return Err(anyhow::anyhow!("time-travel worker panicked: {msg}"));
} Defensive patterns
Strategy: try-catch
Validate before calling
// pre-flight: run the worker logic on a sample repo to surface panics early
worker_smoke_test(&repo).expect("time-travel worker logic should not panic"); Type guard
fn panic_message(e: std::boxed::Box<dyn std::any::Any + Send>) -> String {
e.downcast_ref::<String>().cloned()
.or_else(|| e.downcast_ref::<&str>().map(|s| s.to_string()))
.unwrap_or_else(|| "unknown panic".into())
} Try / catch
match worker.join() {
Ok(v) => v,
Err(payload) => return Err(anyhow::anyhow!("time-travel worker panicked: {}", panic_message(payload))),
} Prevention
- Replace `unwrap()` in worker code with error propagation.
- Run the animation/rebase worker body under `catch_unwind` and report via the event channel.
- Add panic hooks with backtraces to diagnose worker panics quickly.
When it happens
Trigger: `worker.join()` returns `Err(_)` — the time-travel render/rebase worker thread panicked (e.g. an unwrap/index panic in the animation or rebase-plan code running on that thread).
Common situations: A panic inside worker-side rendering code (bad frame math), object lookups that panic on missing objects, or any `unwrap()` in the worker body triggered by unusual repository state during time-travel animation.
Related errors
- rebase worker panicked
- 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
AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08).
Data as JSON: /api/errors/6b19350c62c6bd1c.
Report an issue: GitHub.
Appendix: source
Thrown at gix-tix/src/lib.rs:5790
std::thread::sleep(FRAME_INTERVAL.saturating_sub(last_draw.elapsed()));
}
let id = latest.expect("a changed rebased commit is available");
if let Err(err) = render(id) {
render_error = Some(err);
continue;
}
rendered = latest;
last_draw = Some(Instant::now());
}
if let Some(result) = complete.take() {
break result;
}
};
if let Some(err) = render_error {
tracing::warn!(error = %err, "time-travel animation stopped");
}
if worker.join().is_err() {
return Err(anyhow::anyhow!("time-travel worker panicked"));
}
result
})
}
fn run_rebase_plan(
terminal: &mut ratatui::DefaultTerminal,
repository: gix::ThreadSafeRepository,
graph: &HistoryGraph,
plan: edit::rebase::Plan,
) -> Result<edit::rebase::PlanPerform> {
run_with_todo_progress(terminal, move |report| {
let mut repository = repository.to_thread_local();
repository.object_cache_size(None);
edit::rebase::perform_plan_with_progress(&repository, graph, plan, report)
})
}
View on GitHub (pinned to e73179060b)