rust-lang/cargo · error
several `[patch]` entries resolving to same version
Error message
several `[patch]` entries resolving to same version `{} v{}`
help: check `{}` patch definitions for `{}` in {} What it means
Multiple `[patch]` entries that resolve the same package to the same `(name, version)` pair create ambiguity — Cargo cannot choose between them. After collecting all unlocked summaries, the registry builds a `HashSet` of `(name, version)` and bails on the first duplicate, listing the offending patch locations.
Solutions
- Keep only one `[patch]` entry per (package, version) and remove duplicates from other manifests.
- If different patches target different versions, ensure their version requirements are disjoint.
- Centralize all patches in the workspace root `[patch]` table.
Example fix
# before (root Cargo.toml)
[patch.crates-io]
foo = { git = "https://example.com/a/foo" }
# (and, in a member Cargo.toml)
[patch.crates-io]
foo = { git = "https://example.com/b/foo" }
# after (single entry in root)
[patch.crates-io]
foo = { git = "https://example.com/a/foo" } Defensive patterns
Strategy: validation
Validate before calling
use std::collections::HashSet;
fn patches_resolve_uniquely(patches: &[(String, semver::Version)]) -> bool {
let mut seen = HashSet::new();
patches.iter().all(|(n, v)| seen.insert((n.clone(), v.clone())))
}
// gather (name, version) for each patch target before resolution Prevention
- Centralize `[patch]` entries in the workspace root.
- Audit for duplicate patches across member manifests after merges.
- Use disjoint version requirements when multiple patches are intentional.
When it happens
Trigger: Two `[patch.crates-io] foo = ...` entries (in the root or different manifests) whose targets both yield `foo 1.2.0`. The `!name_and_version.insert((name, version))` check at registry.rs:463 fails.
Common situations: Patching the same crate from both a workspace manifest and a member manifest. Merging patches from multiple sources during a monorepo consolidation. Stale patches left after a dependency was consolidated.
Related errors
- patch for ` ` in ` ` resolved to more than one…
- patch ` ` version mismatch note: patch location contains …
- found patches and a path override
- patch for ` ` points to the same source, but patches must…
- patch location ` ` does not contain packages matching `…
AI-assisted analysis of rust-lang/cargo@98a09e7e7d (2026-08-11).
Data as JSON: /api/errors/dccb8058fd89f6bb.
Report an issue: GitHub.
Appendix: source
Thrown at src/workspace/registry.rs:460
url,
orig_patch.loc
));
}
Ok(summary)
}).collect::<CargoResult<Vec<_>>>()?;
let mut name_and_version = HashSet::default();
for summary in unlocked_summaries.iter() {
let name = summary.package_id().name();
let version = summary.package_id().version();
if !name_and_version.insert((name, version)) {
let duplicate_locations = patch_deps
.iter()
.filter(|&p| p.0.dep.package_name() == name)
.map(|p| format!("`{}`", p.0.loc))
.unique()
.join(", ");
return Err(anyhow::anyhow!(
"several `[patch]` entries resolving to same version `{} v{}`\n\
help: check `{}` patch definitions for `{}` in {}",
name,
version,
name,
url,
duplicate_locations
));
}
}
// Calculate a list of all patches available for this source.
let mut ids = Vec::new();
for (summary, (_, lock)) in unlocked_summaries.iter().zip(patch_deps) {
ids.push(summary.package_id());
// This is subtle where the list of `ids` for a canonical URL is
// extend with possibly two ids per summary. This is done to handle
// the transition from the v2->v3 lock file format where in v2View on GitHub (pinned to 98a09e7e7d)