gitbutlerapp/gitbutler · error
handled above
Error message
handled above
What it means
During but-graph initialization, segment tips are matched on `TipRole`; `TipRole::TargetRemote` is marked `unreachable!("handled above")` because remote-target tips are selected and processed in an earlier phase of the same loop, so by the time this match runs no TargetRemote tips remain. Like the sibling 'handled above' markers, it is an ordering invariant: the panic fires only if the earlier TargetRemote handling is removed or made incomplete while this match still assumes it.
Source
Thrown at crates/but-graph/src/init/mod.rs:2227
(None, CommitFlags::empty()),
target_limit,
commit_graph,
repo,
buf,
)?;
}
continue;
}
let (flags, limit) = match &tip.role {
TipRole::Reachable if tip.is_entrypoint => {
graph.entrypoint = Some((segment, EntryPointCommit::AtCommit(tip.id)));
(entrypoint_flags, max_limit)
}
TipRole::Reachable => {
reachable_tip_flags_and_limit(tip.id, entrypoint, max_limit, goals)
}
TipRole::TargetRemote => unreachable!("handled above"),
TipRole::Workspace => {
if tip.is_entrypoint && graph.entrypoint.is_none() {
graph.entrypoint = Some((segment, EntryPointCommit::AtCommit(tip.id)));
}
let extra_flags = if tip.is_entrypoint {
entrypoint_flags
} else {
CommitFlags::empty()
};
let limit = if tip.is_entrypoint {
max_limit
} else {
max_limit.with_indirect_goal(entrypoint, goals)
};
(
CommitFlags::InWorkspace | CommitFlags::NotInRemote | extra_flags,
limit,
)View on GitHub (pinned to caf1f223d3)
Solutions
- Keep the early TargetRemote pass exhaustive over all tip sources before this match runs.
- Replace `unreachable!` with a defensive `continue` (plus a `debug_assert!` or tracing warning) if the invariant is hard to guarantee during refactors.
- Add a graph-init fixture with remote-target tips to the snapshot tests so reordering breaks tests, not production.
Example fix
// before
TipRole::TargetRemote => unreachable!("handled above"),
// after
TipRole::TargetRemote => {
// ordering invariant: consumed in the earlier pass; keep safe during refactors
debug_assert!(false, "TargetRemote should have been handled above");
continue;
} Defensive patterns
Strategy: type-guard
Type guard
fn consumed_earlier(role: &TipRole) -> bool {
matches!(role, TipRole::TargetRemote)
} Prevention
- Keep the early TargetRemote selection pass exhaustive before the tip-role match runs.
- When reordering the loop, convert unreachable! arms to defensive continues with debug_assert!.
- Maintain graph-init fixtures containing remote-target tips so ordering breaks in tests first.
When it happens
Trigger: Refactoring the tip-processing loop so TargetRemote tips are no longer fully consumed earlier; adding new tip sources that inject TargetRemote roles after the early phase; merges that reorder the two passes.
Common situations: Graph-initialization refactors in but-graph; extending `TipRole` with new remote-tracking semantics; snapshot-test failures after reordering logic.
Related errors
- BUG: {id} is queued
- handled above
- candidate turns always have review or branch evidence
- validated AI responses only produce content picks
- we never return these as the status iteration is configured
AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20).
Data as JSON: /api/errors/d2f9f42d6ced11ae.
Report an issue: GitHub.