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

  1. Remove the duplicate specifier from the artifact list before calling Artifact::parse.
  2. If building the list programmatically, dedup the input strings (or the parsed ArtifactKind values) before validation.
  3. 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

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


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)