{"record":{"id":"24a764135e223c78","repo":"rust-lang/cargo","slug":"patch-for-in-resolved-to-more-than-one-c","errorCode":null,"errorMessage":"patch for `{}` in `{}` resolved to more than one candidate\nnote: found versions: {}\nhelp: check `{}` patch definition for `{}` in `{}`\nhelp: select only one package using `version = \"={}\"`","messagePattern":"patch for `(.+?)` in `(.+?)` resolved to more than one candidate\nnote: found versions: (.+?)\nhelp: check `(.+?)` patch definition for `(.+?)` in `(.+?)`\nhelp: select only one package using `version = \"=(.+?)\"`","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/workspace/registry.rs","lineNumber":980,"sourceCode":"    locked: &Option<LockedPatchDependency>,\n    mut summaries: Vec<Summary>,\n    source: &dyn Source,\n) -> CargoResult<(Summary, Option<PackageId>)> {\n    if summaries.len() == 1 {\n        return Ok((summaries.pop().unwrap(), None));\n    }\n    if summaries.len() > 1 {\n        // TODO: In the future, it might be nice to add all of these\n        // candidates so that version selection would just pick the\n        // appropriate one. However, as this is currently structured, if we\n        // added these all as patches, the unselected versions would end up in\n        // the \"unused patch\" listing, and trigger a warning. It might take a\n        // fair bit of restructuring to make that work cleanly, and there\n        // isn't any demand at this time to support that.\n        let mut vers: Vec<_> = summaries.iter().map(|summary| summary.version()).collect();\n        vers.sort();\n        let versions: Vec<_> = vers.into_iter().map(|v| v.to_string()).collect();\n        return Err(anyhow::anyhow!(\n            \"patch for `{}` in `{}` resolved to more than one candidate\\n\\\n            note: found versions: {}\\n\\\n            help: check `{}` patch definition for `{}` in `{}`\\n\\\n            help: select only one package using `version = \\\"={}\\\"`\",\n            &original_patch.dep.package_name(),\n            &original_patch.dep.source_id(),\n            versions.join(\", \"),\n            &original_patch.dep.package_name(),\n            orig_patch_url,\n            original_patch.loc,\n            versions.last().unwrap()\n        ));\n    }\n    assert!(summaries.is_empty());\n    // No summaries found, try to help the user figure out what is wrong.\n    if let Some(locked) = locked {\n        // Since the locked patch did not match anything, try the unlocked one.\n        let orig_matches = source","sourceCodeStart":962,"sourceCodeEnd":998,"githubUrl":"https://github.com/rust-lang/cargo/blob/98a09e7e7d62850f14e5b6132101fc1edd19a16f/src/workspace/registry.rs#L962-L998","documentation":"A `[patch]` entry matched more than one candidate version in the target source. Cargo requires a patch to resolve to exactly one package; multiple matches are ambiguous. The registry collects all matched summaries, and if `summaries.len() > 1` it sorts them and bails, suggesting the user pin with `version = \"=<highest>\"`.","triggerScenarios":"`[patch.crates-io] foo = { git = \"https://...\" }` where the git repo publishes multiple versions of `foo` (e.g. 1.0.0 and 1.1.0) with no version constraint to disambiguate.","commonSituations":"Patching to a fork or monorepo that contains several versions of the crate. Forgetting the `version` key in a patch entry. Upstream repo gaining new versions after the patch was written.","solutions":["Add a `version` requirement to the patch to select one candidate, e.g. `version = \"=1.1.0\"`.","Point the patch at a git rev/tag that contains only the desired version.","Use a path patch to a checkout holding a single version."],"exampleFix":"# before\n[patch.crates-io]\nfoo = { git = \"https://example.com/foo-fork\" }\n\n# after\n[patch.crates-io]\nfoo = { git = \"https://example.com/foo-fork\", version = \"=1.1.0\" }","handlingStrategy":"validation","validationCode":"// Pre-check: a patch should select exactly one candidate version\nfn patch_has_single_candidate(available: &[semver::Version], req: &semver::VersionReq) -> bool {\n    available.iter().filter(|v| req.matches(v)).count() == 1\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Add a `version` requirement (ideally `=\"X.Y.Z\"`) to every patch entry.","Pin patches to a specific git rev/tag.","Re-check patches after the fork gains new versions."],"tags":["cargo","patch","registry","version-resolution","config"],"backgroundTag":null,"analyzedSha":"98a09e7e7d62850f14e5b6132101fc1edd19a16f","analyzedAt":"2026-08-11T17:42:36.556Z","contentChangedAt":"2026-08-11T17:42:36.556Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}