rust-lang/cargo · error
found build scripts with duplicate file stems, but all…
Error message
found build scripts with duplicate file stems, but all build scripts must have a unique file stem
What it means
When `package.build` lists multiple build scripts (`MultipleScript`), each must have a unique file stem because Cargo derives the generated target name as `build-script-<stem>`. `validate_unique_build_scripts` groups paths by stem and bails if any stem maps to more than one path, listing the offenders.
Solutions
- Give each build script a distinct file name, e.g. `a/a_build.rs` and `b/b_build.rs`.
- Consolidate the logic of duplicate-stem scripts into a single build script.
- Re-run `cargo check` to confirm stems are unique.
Example fix
# before [package] build = ["a/build.rs", "b/build.rs"] # after [package] build = ["a/a_build.rs", "b/b_build.rs"]
Defensive patterns
Strategy: validation
Validate before calling
use std::collections::HashMap;
fn build_scripts_unique_stems(scripts: &[String]) -> bool {
let mut stems: HashMap<String, usize> = HashMap::new();
for s in scripts {
if let Some(stem) = std::path::Path::new(s).file_stem().and_then(|x| x.to_str()) {
*stems.entry(stem.to_string()).or_default() += 1;
}
}
stems.values().all(|c| *c == 1)
} Prevention
- Name multi-script builds with distinct stems (e.g. `a_build.rs`).
- Avoid placing every script at `<dir>/build.rs`.
- Validate stems before committing a multi-script `build` list.
When it happens
Trigger: `[package] build = ["a/build.rs", "b/build.rs"]` — both files have stem `build`. The `paths.len() > 1` branch at targets.rs:922 flags the stem and bails after building the message.
Common situations: Organizing build scripts in subdirectories that share the conventional `build.rs` name. Merging two crates' build steps into one package. Renaming directories but not the script files.
Related errors
- invalid `package.build` file name
- cannot specify both `metabuild` and `build`
- found duplicate name , but all targets must have a unique…
- target .name is required
- target names cannot be empty
AI-assisted analysis of rust-lang/cargo@eb98b54bc9 (2026-08-11).
Data as JSON: /api/errors/0a896bf0fae96852.
Report an issue: GitHub.
Appendix: source
Thrown at src/workspace/parser/targets.rs:928
.file_stem()
.and_then(|s| s.to_str())
.expect("previously normalized");
seen.entry(stem)
.or_insert_with(Vec::new)
.push(script.as_str());
}
let mut conflict_file_stem = false;
let mut err_msg = String::from(
"found build scripts with duplicate file stems, but all build scripts must have a unique file stem",
);
for (stem, paths) in seen {
if paths.len() > 1 {
conflict_file_stem = true;
write!(&mut err_msg, "\n for stem `{stem}`: {}", paths.join(", "))?;
}
}
if conflict_file_stem {
anyhow::bail!(err_msg);
}
Ok(())
}
fn configure(
toml: &TomlTarget,
target: &mut Target,
target_kind_human: &str,
warnings: &mut Vec<String>,
) -> CargoResult<()> {
let t2 = target.clone();
target
.set_tested(toml.test.unwrap_or_else(|| t2.tested()))
.set_doc(toml.doc.unwrap_or_else(|| t2.documented()))
.set_doctest(toml.doctest.unwrap_or_else(|| t2.doctested()))
.set_benched(toml.bench.unwrap_or_else(|| t2.benched()))
.set_harness(toml.harness.unwrap_or_else(|| t2.harness()))
.set_proc_macro(toml.proc_macro().unwrap_or_else(|| t2.proc_macro()))View on GitHub (pinned to eb98b54bc9)