rust-lang/cargo · error
cannot specify both recursive and precise simultaneously
Error message
cannot specify both recursive and precise simultaneously
What it means
Thrown by `cargo update` when both `--recursive` and `--precise <version>` are passed simultaneously. These flags are mutually exclusive: `--recursive` upgrades an entire dependency subtree, while `--precise` pins a single package to an exact version. Combining them is semantically contradictory.
Solutions
- Use `--precise` alone to pin one package: `cargo update --precise 1.2.3 <pkg>`.
- Use `--recursive` alone to upgrade a full subtree: `cargo update --recursive <pkg>`.
- Remove one of the two conflicting flags from the command.
Example fix
# Before cargo update --recursive --precise 1.2.3 serde # After — choose one cargo update --precise 1.2.3 serde # or cargo update --recursive serde
Defensive patterns
Strategy: validation
Validate before calling
fn validate_update_opts(recursive: bool, precise: Option<&str>) -> Result<(), String> {
if recursive && precise.is_some() {
return Err("cannot use --recursive and --precise together".into());
}
Ok(())
} Prevention
- Use `--recursive` OR `--precise`, never both.
- Read `cargo update --help` to understand flag semantics.
- In scripts, validate flags before invoking cargo.
When it happens
Trigger: Running `cargo update --recursive --precise 1.2.3 <pkg>` or calling `update_lockfile` with `UpdateOptions` where both `recursive` is true and `precise` is `Some(...)`.
Common situations: Misunderstanding the flags; copy-pasting a command with both flags; scripting cargo update with incorrect option combinations.
Related errors
AI-assisted analysis of rust-lang/cargo@98a09e7e7d (2026-08-11).
Data as JSON: /api/errors/1b45143565310eb7.
Report an issue: GitHub.
Appendix: source
Thrown at src/ops/cargo_update.rs:54
let previous_resolve = None;
let mut resolve = ops::resolve_with_previous(
&mut registry,
ws,
&CliFeatures::new_all(true),
HasDevUnits::Yes,
previous_resolve,
None,
&[],
true,
)?;
ops::write_pkg_lockfile(ws, &mut resolve)?;
print_lockfile_changes(ws, previous_resolve, &resolve, &mut registry)?;
Ok(())
}
pub fn update_lockfile(ws: &Workspace<'_>, opts: &UpdateOptions<'_>) -> CargoResult<()> {
if opts.recursive && opts.precise.is_some() {
anyhow::bail!("cannot specify both recursive and precise simultaneously")
}
if ws.members().count() == 0 {
anyhow::bail!("you can't generate a lockfile for an empty workspace.")
}
// Updates often require a lot of modifications to the registry, so ensure
// that we're synchronized against other Cargos.
let _lock = ws
.gctx()
.acquire_package_cache_lock(CacheLockMode::DownloadExclusive)?;
let previous_resolve = match ops::load_pkg_lockfile(ws)? {
Some(resolve) => resolve,
None => {
match opts.precise {
None => return generate_lockfile(ws),
View on GitHub (pinned to 98a09e7e7d)