GitoxideLabs/gitoxide · error
BUG: this method may only be called until it is successful
Error message
BUG: this method may only be called until it is successful
What it means
main_worktree_inner() asserts self.repo is still Some. PrepareCheckout owns the Repository in an Option and removes it once checkout succeeds and the repository is handed to the caller. Calling this method after a successful completion (or after persist/Drop consumed it) violates the type's state machine and panics.
Solutions
- Call main_worktree() exactly once; consume the returned Repository and never reuse the PrepareCheckout value.
- Recreate the PrepareCheckout instance (via Clone::prepare_fetch/clone) if you need to retry checkout.
- If you need the repository after success, use the Repository returned from the successful call.
Example fix
// before let repo1 = prepare.main_worktree(...)?; let repo2 = prepare.main_worktree(...)?; // panics: already consumed // after let repo = prepare.main_worktree(...)?;
Defensive patterns
Strategy: type-guard
Validate before calling
// PrepareCheckout is crate-internal here; at the call site ensure main_worktree() is invoked once: assert!(!consumed, "PrepareCheckout already completed");
Prevention
- Call main_worktree() exactly once per PrepareCheckout.
- Do not reuse the value in retry loops; construct a fresh PrepareCheckout instead.
- Treat the success path as consuming the value (like persist()).
When it happens
Trigger: Calling main_worktree()/main_worktree_inner() a second time on the same PrepareCheckout value after a previous call succeeded and moved the repo out.
Common situations: Retry loops that re-invoke prepare without rebuilding it; code paths that continue after the value was consumed; misuse of the internal (crate-private) API during refactoring.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- present as checkout operation isn't complete
- ' ' 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/1c408122c7015cac.
Report an issue: GitHub.
Appendix: source
Thrown at gix/src/clone/checkout.rs:94
should_interrupt: &AtomicBool,
) -> Result<(Repository, gix_worktree_state::checkout::Outcome), Error>
where
P: gix_features::progress::NestedProgress,
P::SubProgress: gix_features::progress::NestedProgress + 'static,
{
self.main_worktree_inner(&mut progress, should_interrupt)
}
fn main_worktree_inner(
&mut self,
progress: &mut dyn gix_features::progress::DynNestedProgress,
should_interrupt: &AtomicBool,
) -> Result<(Repository, gix_worktree_state::checkout::Outcome), Error> {
let _span = gix_trace::coarse!("gix::clone::PrepareCheckout::main_worktree()");
let repo = self
.repo
.as_ref()
.expect("BUG: this method may only be called until it is successful");
let workdir = repo.workdir().ok_or_else(|| Error::BareRepository {
git_dir: repo.git_dir().to_owned(),
})?;
let root_tree_id = match &self.ref_name {
Some(reference_val) => Some(repo.find_reference(reference_val)?.peel_to_id()?),
None => repo.head()?.try_peel_to_id()?,
};
let root_tree = match root_tree_id {
Some(id) => id.object().expect("downloaded from remote").peel_to_tree()?.id,
None => {
return Ok((
self.repo.take().expect("still present"),
gix_worktree_state::checkout::Outcome::default(),
));
}
};View on GitHub (pinned to e73179060b)