GitoxideLabs/gitoxide · error
present and consumed once
Error message
present and consumed once
What it means
PrepareCheckout::persist() calls self.repo.take().expect("present and consumed once"). It consumes the value via `mut self`, so the Option must still be Some when persist runs. It panics if the repository was already taken - i.e. persist() was called twice, or the repo was already handed over by a successful checkout flow before persist().
Solutions
- Call persist() exactly once; persist consumes self so the value cannot be used afterwards.
- If checkout succeeded, use the Repository returned by main_worktree() instead of calling persist().
- Rely on Drop to persist automatically if you cannot decide in code - do not double-persist.
Example fix
// before let repo = prepare.persist(); let again = prepare.persist(); // compile error / cannot reuse; pattern of double-consume panics in Drop paths // after let repo = prepare.persist(); // exactly once, value consumed
Defensive patterns
Strategy: validation
Validate before calling
// persist() consumes self, so the compiler enforces single use; ensure one code path owns it: let repo = prepare.persist();
Prevention
- Call persist() exactly once, as the final operation on the value.
- Do not call persist() after checkout already handed you the Repository.
- Rely on move semantics: pass PrepareFetch/Checkout into a single finishing function.
When it happens
Trigger: Calling persist() twice on the same PrepareCheckout; calling persist() after main_worktree() succeeded and the caller already owns the Repository; calling persist() after the value was previously consumed internally.
Common situations: Error-handling paths that persist in multiple branches; storing the value and calling persist in a helper plus a fallback; confusing persist() with a getter.
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 and consumed once
- ' ' 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/83adf8c014ee7b89.
Report an issue: GitHub.
Appendix: source
Thrown at gix/src/clone/checkout.rs:167
/// Access
impl PrepareCheckout {
/// Get access to the repository while the checkout isn't yet completed.
///
/// # Panics
///
/// If the checkout is completed and the [`Repository`] was already passed on to the caller.
pub fn repo(&self) -> &Repository {
self.repo
.as_ref()
.expect("present as checkout operation isn't complete")
}
}
/// Consumption
impl PrepareCheckout {
/// Persist the contained repository as is even if an error may have occurred when checking out the main working tree.
pub fn persist(mut self) -> Repository {
self.repo.take().expect("present and consumed once")
}
}
impl Drop for PrepareCheckout {
fn drop(&mut self) {
if let Some(repo) = self.repo.take() {
super::cleanup_clone_destination_on_drop(&repo, self.remove_worktree_on_drop);
}
}
}
impl From<PrepareCheckout> for Repository {
fn from(prep: PrepareCheckout) -> Self {
prep.persist()
}
}
View on GitHub (pinned to e73179060b)