rust-lang/cargo · error
Found duplicate binary artifact
Error message
Found {} duplicate binary artifact{} What it means
Thrown by ArtifactKind::validate() when parsing a list of artifact specifiers (e.g. for cargo artifact selection). After collecting all kinds, it sorts and dedups them; if the original list had more entries than the deduped list, duplicates were present. The count and pluralization are interpolated into the message. This guards the Artifact::parse entry point used when a caller passes a slice of artifact strings like ['bin','cdylib','bin'].
Solutions
- Remove the duplicate specifier from the artifact list before calling Artifact::parse.
- If building the list programmatically, dedup the input strings (or the parsed ArtifactKind values) before validation.
- If the duplicate is unintentional from CLI parsing, audit how repeated flags are collected (append vs overwrite).
Example fix
// before let artifacts = vec!["cdylib", "cdylib", "staticlib"]; let art = Artifact::parse(&artifacts, true, None, false)?; // errors // after let artifacts = vec!["cdylib", "staticlib"]; let art = Artifact::parse(&artifacts, true, None, false)?;
Defensive patterns
Strategy: validation
Validate before calling
fn dedup_artifacts(specs: &[String]) -> Vec<String> {
let mut seen = std::collections::HashSet::new();
let mut out = Vec::new();
for s in specs {
if seen.insert(s.clone()) { out.push(s.clone()); }
}
out
}
// call before Artifact::parse
let clean = dedup_artifacts(&user_artifacts);
let artifact = Artifact::parse(&clean, is_lib, target, unstable)?; Type guard
fn has_duplicate_artifacts(specs: &[impl AsRef<str>]) -> bool {
let mut seen = std::collections::HashSet::new();
specs.iter().any(|s| !seen.insert(s.as_ref().to_owned()))
} Try / catch
match Artifact::parse(&artifacts, is_lib, target, unstable) {
Ok(a) => a,
Err(e) if e.to_string().contains("duplicate binary artifact") => {
// dedup and retry once
let deduped: Vec<_> = artifacts.iter().collect::<HashSet<_>>().into_iter().collect();
Artifact::parse(&deduped, is_lib, target, unstable)?
}
Err(e) => return Err(e),
} Prevention
- Always dedup user-supplied artifact lists before passing to Artifact::parse.
- Use a HashSet when collecting artifact flags from repeated CLI args.
- Log the raw artifact list when validation fails to surface the duplicate quickly.
When it happens
Trigger: Calling Artifact::parse (or a higher-level API forwarding an artifact list) with a list containing the same specifier more than once, e.g. ['cdylib','cdylib'] or ['bin:foo','bin:foo']. Each string is parsed via ArtifactKind::parse and the resulting Vec is passed to ArtifactKind::validate, which detects the size mismatch after sort+dedup.
Common situations: A build tool or cargo subcommand forwards user-supplied --artifact flags into a list and the user repeated one. Script-generated artifact lists that append rather than replace. Aliasing bugs where two CLI flags collapse to the same ArtifactKind.
Related errors
- Cannot specify both 'bin' and 'bin
- found build scripts with duplicate file stems, but all…
- found duplicate name , but all targets must have a unique…
- invalid `package.build` file name
- ' ' is not a valid artifact specifier
AI-assisted analysis of rust-lang/cargo@98a09e7e7d (2026-08-11).
Data as JSON: /api/errors/bf8e6e8a4c1c9f8a.
Report an issue: GitHub.
Appendix: source
Thrown at src/workspace/dependency.rs:669
})
}
fn validate(kinds: Vec<ArtifactKind>) -> CargoResult<Vec<ArtifactKind>> {
if kinds.iter().any(|k| matches!(k, ArtifactKind::AllBinaries))
&& kinds
.iter()
.any(|k| matches!(k, ArtifactKind::SelectedBinary(_)))
{
anyhow::bail!(
"Cannot specify both 'bin' and 'bin:<name>' binary artifacts, as 'bin' selects all available binaries."
);
}
let mut kinds_without_dupes = kinds.clone();
kinds_without_dupes.sort();
kinds_without_dupes.dedup();
let num_dupes = kinds.len() - kinds_without_dupes.len();
if num_dupes != 0 {
anyhow::bail!(
"Found {} duplicate binary artifact{}",
num_dupes,
(num_dupes > 1).then(|| "s").unwrap_or("")
);
}
Ok(kinds)
}
}
/// Patch is a dependency override that knows where it has been defined.
/// See [`PatchLocation`] for possible locations.
#[derive(Clone, Debug)]
pub struct Patch {
pub dep: Dependency,
pub loc: PatchLocation,
}
/// Place where a [`Patch`] has been defined.View on GitHub (pinned to 98a09e7e7d)