rust-lang/cargo · error · anyhow::Error
package collision in the lockfile: packages {} and {} are di
Error message
package collision in the lockfile: packages {} and {} are different, but only one can be written to lockfile unambiguously What it means
Produced by `check_duplicate_pkgs_in_lockfile`: two genuinely different `PackageId`s encode to the same lossy lockfile representation (the lockfile omits path-dependency paths, so two distinct path/git packages with same name+version+source-type collapse to one encodable ID). Cargo refuses to write an ambiguous lockfile.
Source
Thrown at src/resolver/mod.rs:1074
}
visited.remove(&id);
Ok(())
}
}
/// Checks that packages are unique when written to lock file.
///
/// When writing package ID's to lock file, we apply lossy encoding. In
/// particular, we don't store paths of path dependencies. That means that
/// *different* packages may collide in the lock file, hence this check.
fn check_duplicate_pkgs_in_lockfile(resolve: &Resolve) -> CargoResult<()> {
let mut unique_pkg_ids = HashMap::default();
let state = encode::EncodeState::new(resolve);
for pkg_id in resolve.iter() {
let encodable_pkd_id = encode::encodable_package_id(pkg_id, &state, resolve.version());
if let Some(prev_pkg_id) = unique_pkg_ids.insert(encodable_pkd_id, pkg_id) {
anyhow::bail!(
"package collision in the lockfile: packages {} and {} are different, \
but only one can be written to lockfile unambiguously",
prev_pkg_id,
pkg_id
)
}
}
Ok(())
}
View on GitHub (pinned to 0e07a15537)
Solutions
- Bump the version of one of the colliding crates so they differ (e.g. `1.0.0` → `1.0.1`).
- Consolidate both dependencies to point at the same single source location.
- If one copy is vendored, remove the duplicate path dependency and use the canonical one.
Example fix
# before: two path deps both named foo v1.0.0 at different paths # after # edit one fork's Cargo.toml: version = "1.0.1"
Defensive patterns
Strategy: validation
Validate before calling
# In CI, ensure no two path deps share name+version: cargo metadata --no-deps --format-version 1 | \ jq '.packages | group_by(.name + .version) | map(select(length > 1)) | length' \ | grep -qw 0 || echo 'duplicate name+version path packages'
Prevention
- Give internal crates unique versions per source location.
- Avoid vendoring the same crate from two paths.
- Consolidate duplicate path deps to a single canonical source.
When it happens
Trigger: Two workspace path dependencies, or two git checkouts, sharing the same crate name and version but at different filesystem locations — e.g. `dep = { path = "vendor/a/foo" }` and another crate depending on `dep = { path = "vendor/b/foo" }`, both `foo 1.0.0`. The `unique_pkg_ids.insert` collision triggers the bail.
Common situations: Vendoring the same crate version from two locations; monorepo with multiple copies of an internal crate at the same version; git submodules duplicating a crate; `[patch]` targets that resolve to a name/version clashing with an existing path dep.
Related errors
- you can't generate a lockfile for an empty workspace.
- Lockfile path can't be root
- dependency ({}) specified without providing a local path, Gi
- cannot override workspace dependency with `--default-feature
- cannot override workspace dependency with `--registry`, eith
AI-assisted analysis of rust-lang/cargo@0e07a15537 (2026-08-06).
Data as JSON: /data/errors/a17a5b54c9851e43.json.
Report an issue: GitHub.