rust-lang/cargo · error · anyhow::Error
package `{}` is specified twice in the lockfile
Error message
package `{}` is specified twice in the lockfile What it means
Raised in `into_resolve` while decoding `Cargo.lock`: two entries in the lockfile's `[[package]]` list produce identical encodable IDs (name + version + source). Cargo dedupes via a `HashSet` (`all_pkgs.insert`) and bails on the second insert, because the lockfile format requires each package to appear exactly once.
Source
Thrown at src/resolver/encode.rs:187
packages.insert(0, root);
}
packages
};
// `PackageId`s in the lock file don't include the `source` part
// for workspace members, so we reconstruct proper IDs.
let live_pkgs = {
let mut live_pkgs = HashMap::default();
let mut all_pkgs = HashSet::default();
for pkg in packages.iter() {
let enc_id = TomlLockfilePackageId {
name: pkg.name.clone(),
version: Some(pkg.version.clone()),
source: pkg.source.clone(),
};
if !all_pkgs.insert(enc_id.clone()) {
anyhow::bail!("package `{}` is specified twice in the lockfile", pkg.name);
}
let id = match pkg
.source
.as_ref()
.map(|source| SourceId::from_url(&source.source_str()))
.transpose()?
.or_else(|| get_source_id(&path_deps, &pkg).copied())
{
// We failed to find a local package in the workspace.
// It must have been removed and should be ignored.
None => {
debug!("path dependency now missing {} v{}", pkg.name, pkg.version);
continue;
}
Some(source) => PackageId::try_new(&pkg.name, &pkg.version, source)?,
};
// If a package has a checksum listed directly on it then recordView on GitHub (pinned to 0e07a15537)
Solutions
- Regenerate the lockfile: delete `Cargo.lock` and run `cargo generate-lockfile` or `cargo build`.
- Resolve git merge conflicts in `Cargo.lock` by running `cargo check` rather than hand-merging.
- Audit `Cargo.lock` for duplicate `[[package]]` entries with identical name/version/source and remove the stale one.
Example fix
# before: two [[package]] entries for serde 1.0.184 # after git checkout --theirs Cargo.lock && cargo generate-lockfile
Defensive patterns
Strategy: validation
Validate before calling
# Pre-commit check: never hand-merge Cargo.lock — regenerate instead. # Validate the lockfile parses cleanly: cargo metadata --no-deps --offline >/dev/null || cargo generate-lockfile
Prevention
- Resolve `Cargo.lock` merge conflicts by deleting the file and running `cargo generate-lockfile`, not by hand-merging.
- Run `cargo check` in pre-commit hooks to validate the lockfile.
- Avoid third-party tools that rewrite `Cargo.lock` by hand.
When it happens
Trigger: A manually or programmatically corrupted `Cargo.lock` containing two `[[package]]` blocks with the same name/version/source. Also possible from a botched merge conflict resolution in `Cargo.lock`, or from a tool that rewrites lockfiles incorrectly.
Common situations: Git merge conflicts in `Cargo.lock` resolved by keeping both sides; third-party tools (lockfile editors, dependency scanners) writing duplicate entries; hand-editing `Cargo.lock`.
Related errors
- failed to merge config value from `{}` into `{}`: expected {
- a Cargo.lock must exist for this command
- cannot specify both recursive and precise simultaneously
- you can't generate a lockfile for an empty workspace.
- package ID specification{plural} did not match any direct de
AI-assisted analysis of rust-lang/cargo@0e07a15537 (2026-08-06).
Data as JSON: /data/errors/9ed4b1a87a644442.json.
Report an issue: GitHub.