rust-lang/cargo · error
patch for ` ` points to the same source, but patches must…
Error message
patch for `{}` points to the same source, but patches must point to different sources
help: check `{}` patch definition for `{}` in `{}` What it means
A `[patch]` entry must redirect a dependency to a *different* source than the one being patched; a self-referential patch is meaningless. During summary resolution, the registry compares `summary.package_id().source_id().canonical_url()` against the original source's `canonical` URL and bails if they match. This prevents no-op patches that would create resolution loops.
Solutions
- Point the patch at a genuinely different source: a local path, fork, or different git URL.
- If you only want to pin a version, use `[patch]` with a path to a local checkout rather than the upstream registry.
- Double-check the canonical URLs of both the original and patched sources.
Example fix
# before (self-referential)
[patch.crates-io]
foo = { version = "*", path = "../foo" }
# where ../foo's Cargo.toml still sources from crates.io index
# after (distinct local source)
[patch.crates-io]
foo = { path = "../foo-local-fork" } Defensive patterns
Strategy: validation
Validate before calling
// Before applying a patch, confirm sources differ by canonical URL
fn patch_sources_differ(orig_url: &str, patch_url: &str) -> bool {
// normalize trailing slashes, scheme, host; then compare
normalize(orig_url) != normalize(patch_url)
}
// fn normalize(u: &str) -> String { /* strip trailing '/', lowercase host */ } Try / catch
// When driving cargo programmatically via cargo-the-library:
// match Workspace::new(&root, &config).and_then(|ws| ws.load()).err() {
// Some(e) if e.to_string().contains("points to the same source") => { /* fix patch */ }
// _ => {}
// } Prevention
- Always patch to a distinct source (local path or fork).
- Review `[patch]` URLs for accidental self-references.
- Avoid patching a registry dep to the same registry.
When it happens
Trigger: `[patch.crates-io] foo = { version = "*", path = "../foo" }` where `../foo` resolves to the same registry/git source as crates-io. Or patching a git dependency to the same git URL.
Common situations: Vendoring a crate that still points back to its origin. Circular workspace references. Misconfigured `[patch]` after moving a crate into the same registry index.
Related errors
- patch location ` ` does not contain packages matching `…
- found patches and a path override
- patch for ` ` in ` ` resolved to more than one…
- patch ` ` version mismatch note: patch location contains …
- several `[patch]` entries resolving to same version
AI-assisted analysis of rust-lang/cargo@98a09e7e7d (2026-08-11).
Data as JSON: /api/errors/78763b5f350075eb.
Report an issue: GitHub.
Appendix: source
Thrown at src/workspace/registry.rs:437
let (summary, should_unlock) =
summary_for_patch(&orig_patch, url, &locked, summaries, source.as_ref())
.await?;
Ok::<_, anyhow::Error>((orig_patch, dep, summary, should_unlock))
});
}
let unlocked_summaries = crate::util::block_on_stream(pending).map(|next| {
let (orig_patch, dep, summary, should_unlock) = next?;
debug!(
"patch summary is {:?} should_unlock={:?}",
summary, should_unlock
);
if let Some(unlock_id) = should_unlock {
unlock_patches.push(((*orig_patch).clone(), unlock_id));
}
if *summary.package_id().source_id().canonical_url() == canonical {
return Err(anyhow::anyhow!(
"patch for `{}` points to the same source, but patches must point to different sources\n\
help: check `{}` patch definition for `{}` in `{}`",
dep.package_name(),
dep.package_name(),
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()View on GitHub (pinned to 98a09e7e7d)