GitoxideLabs/gitoxide · error
rebase worker panicked
Error message
rebase worker panicked
What it means
After the rebase driver loop finishes, the worker thread's `JoinHandle::join()` is checked; a join error means the worker thread panicked rather than returned normally. The panic itself is discarded, so only this generic message is reported to the user.
Solutions
- Capture the panic payload: `match worker.join() { Err(p) => report {:?} of p, ... }` so the real panic message is shown instead of a generic one.
- Run the operation with `RUST_BACKTRACE=1` and reproduce to find the panicking call site in the worker closure.
- Replace `unwrap()`/`expect()` in the worker closure with error propagation via the `Complete(Err(...))` event.
- Check the repository state (corrupt objects, malformed rebase todo) that may trigger the panic path.
Example fix
// before
if worker.join().is_err() {
return Err(anyhow::anyhow!("rebase worker panicked"));
}
// after
if let Err(panic) = worker.join() {
return Err(anyhow::anyhow!("rebase worker panicked: {panic:?}"));
} Defensive patterns
Strategy: try-catch
Validate before calling
// Cannot validate ahead of time; enable panic capture in the worker closure: let worker = thread::spawn(move || std::panic::catch_unwind(AssertUnwindSafe(worker_body)));
Type guard
fn worker_panicked(join: &Result<(), Box<dyn Any + Send>>) -> bool {
join.is_err()
} Try / catch
match worker.join() {
Err(panic) => Err(anyhow::anyhow!("rebase worker panicked: {panic:?}")),
Ok(Err(e)) => Err(e),
Ok(Ok(v)) => Ok(v),
} Prevention
- Never `unwrap()` inside the worker closure; propagate errors via the Complete event
- Run with `RUST_BACKTRACE=1` during development to localize panics
- Validate repository state (objects, todo script) before spawning the worker
- Fuzz worker input with unusual repo states in CI
When it happens
Trigger: The closure passed to the rebase worker thread panicked (e.g. `unwrap()`/index-out-of-bounds inside rebase execution) and `worker.join()` returned `Err` at gix-tix/src/lib.rs:5867.
Common situations: A panic in gix internals triggered by an unusual repository state (corrupt object, bad todo line); a bug such as an out-of-range index while rendering/processing todos; an `expect()` firing in the worker.
Related errors
- time-travel worker panicked
- rebase worker stopped unexpectedly
- continued refs have a target
- a stack always contains HEAD
- ' ' is not a valid configuration key
AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08).
Data as JSON: /api/errors/43490a4f0baec2b8.
Report an issue: GitHub.
Appendix: source
Thrown at gix-tix/src/lib.rs:5867
Some(RebaseWorkerEvent::Progress(progress)) => latest = Some(progress),
Some(RebaseWorkerEvent::Complete(result)) => break result,
None => {}
}
let now = Instant::now();
if todo_progress_visible(now.duration_since(started))
&& latest != rendered
&& now.duration_since(last_draw) >= FRAME_INTERVAL
{
let progress = latest.expect("a changed progress snapshot is available");
if let Err(err) = terminal.draw(|frame| ui::draw_todo_progress(frame, progress)) {
break Err(err).context("could not draw rebase progress");
}
rendered = latest;
last_draw = now;
}
};
if worker.join().is_err() {
return Err(anyhow::anyhow!("rebase worker panicked"));
}
result
})
}
fn todo_progress_visible(elapsed: Duration) -> bool {
elapsed >= TODO_PROGRESS_DELAY
}
#[derive(Clone, Copy)]
enum CreateMode {
Insert,
InsertEmpty,
Fork,
}
#[tracing::instrument(skip_all, fields(parent = ?parent, fork = matches!(mode, CreateMode::Fork)))]
fn create_commit(View on GitHub (pinned to e73179060b)