rust-lang/cargo · error
not currently active!?
Error message
not currently active!?
What it means
Internal debug-only invariant assertion in Cargo's dependency resolver (src/resolver/mod.rs:898). While combining conflict maps during backtracking, the resolver builds a new ConflictMap and then asserts every key in it is still an active package in the current ResolverContext via cx.is_active(c).expect("not currently active!?"). The whole block is wrapped in cfg!(debug_assertions), so it only fires in debug/test builds of cargo; in a release build the branch is dead and never executes. A panic here means the conflict-combining / parent-substitution logic recorded a conflict against a package that the resolver context no longer considers active.
Source
Thrown at src/resolver/mod.rs:898
// A, B are both known bad states each that can never be activated.
// A + B is redundant but can't be activated, as if
// A + B is active then A is active and we know that is not ok.
for (_, other) in &others {
con.extend(other.iter().map(|(&id, re)| (id, re.clone())));
}
// Now that we have this combined conflict, we can do a substitution:
// A dep is equivalent to one of the things it can resolve to.
// So we can remove all the things that it resolves to and replace with the parent.
for (other_id, _) in &others {
con.remove(other_id);
}
con.insert(*critical_parent, backtrack_critical_reason);
if cfg!(debug_assertions) {
// the entire point is to find an older conflict, so let's make sure we did
let new_age = con
.keys()
.map(|&c| cx.is_active(c).expect("not currently active!?"))
.max()
.unwrap();
assert!(
new_age < backtrack_critical_age,
"new_age {} < backtrack_critical_age {}",
new_age,
backtrack_critical_age
);
}
past_conflicting_activations.insert(dep, &con);
return Some(con);
}
}
}
None
}
/// Returns Some of the largest item in the iterator.View on GitHub (pinned to 0e07a15537)
Solutions
- Reproduce with a release cargo build (e.g. `cargo build --release` of cargo) - the assertion is compiled into a dead branch there and will not fire; if resolution succeeds, you have confirmed it is the debug invariant being overly strict, not a real misresolution.
- Reduce the failing Cargo.toml with `cargo repro` / manual minimization to the smallest dependency set that reproduces the panic and attach it to a rust-lang/cargo issue so the resolver bookkeeping bug can be fixed.
- On a debug build, bisect cargo commits around the resolver / backtracking changes to find which change broke the invariant.
- As a workaround for the graph itself, pin or loosen specific dependency versions so the conflict-combining path is not exercised.
Example fix
// before: debug cargo panics on a messy graph // RUSTFLAGS='' cargo run --build -j8 # dev profile => cfg!(debug_assertions) true // thread 'main' panicked at src/resolver/mod.rs:898: not currently active!? // after: confirm with a release binary where the assertion is dead // cargo build --release // ./target/release/cargo build // then report the minimized repro to rust-lang/cargo.
Defensive patterns
Strategy: fallback
Validate before calling
// Not guardable from caller code (internal resolver invariant).
// Pre-check that you are not on a debug cargo build before relying on resolution:
fn assert_release_cargo() {
// cfg!(debug_assertions) is false => the failing branch at mod.rs:894-907 is dead.
assert!(!cfg!(debug_assertions), "this graph trips a debug-only resolver assertion; use a release cargo");
} Type guard
// No type-level guard: PackageId / ConflictMap are internal to cargo. // Only narrowing available is 'is this a release binary?', which removes the panic site.
Try / catch
// Panics are not normally caught in cargo. If you embed cargo as a library,
// isolate the resolving thread and catch_unwind to degrade gracefully:
use std::panic;
let result = panic::catch_unwind(|| {
// ... call into cargo's resolve ...
});
if result.is_err() {
// fall back to a release cargo or a simplified manifest; do NOT silently retry unchanged.
} Prevention
- Run cargo from a release toolchain (rustup stable) for real resolutions; keep debug builds for hacking on cargo itself.
- Keep dependency graphs reasonably constrained (avoid huge optional-dep matrices) to stay off the deep backtracking path.
- When developing cargo, run the resolver test suite before trusting a local debug binary on a real workspace.
When it happens
Trigger: Running a debug build of cargo (or cargo's own test suite) against a dependency graph that forces the backtracking 'find an older conflict' optimization in find_candidate's sibling logic: multiple parents of a critical activation, where past_conflicting_activations.find(...) yields a combined conflict that, after substituting critical_parent, still references a package id whose is_active() returns None.
Common situations: Hacking on cargo itself with a dev build; running cargo resolver tests; a complex workspace with many conflicting semver requirements and yanked/publish-age-restricted crates that drive deep backtracking. Not reproducible with a stock release cargo from rustup.
Related errors
- why did we save a frame that has no next?
- parent not currently active!?
- an already used dep now pending!?
- We've already checked that there is exactly one.
- source ID should have valid URLs
AI-assisted analysis of rust-lang/cargo@0e07a15537 (2026-08-06).
Data as JSON: /data/errors/bc7d59411fb405bb.json.
Report an issue: GitHub.