rust-lang/cargo · error
cannot specify both `metabuild` and `build`
Error message
cannot specify both `metabuild` and `build`
What it means
Cargo supports two mutually-exclusive build script mechanisms: a traditional `build.rs` (via `package.build`) and `metabuild` (a list of build-dependency crates that generate build scripts). The parser reads `package.normalized_build()` and checks `metabuild.is_some()` in the same branch; if both are present it bails immediately. Only one system may drive the build.
Solutions
- Remove the `build` key (or delete build.rs) if you intend to use `metabuild`.
- Remove the `metabuild` key if you intend to keep your traditional build script.
- Run `cargo check` after editing to confirm only one mechanism remains.
Example fix
# before [package] build = "build.rs" metabuild = ["metabuild-crate"] # after (metabuild chosen) [package] metabuild = ["metabuild-crate"]
Defensive patterns
Strategy: validation
Validate before calling
# Pre-flight TOML check before invoking cargo
use toml::Value;
fn has_both_build_and_metabuild(manifest: &Value) -> bool {
let pkg = manifest.get("package");
pkg.and_then(|p| p.get("build")).is_some()
&& pkg.and_then(|p| p.get("metabuild")).is_some()
}
// assert!(!has_both_build_and_metabuild(&parsed)); Prevention
- Treat `build` and `metabuild` as mutually exclusive in manifest linters.
- When migrating to metabuild, remove the `build` key in the same commit.
- Run `cargo check` in CI to catch manifest conflicts early.
When it happens
Trigger: Cargo.toml sets `[package] build = "build.rs"` (or relies on the default `build.rs` convention) AND also declares `[package] metabuild = ["some-crate"]`. The `if let Some(custom_build) ... { if metabuild.is_some() { bail! } }` block at targets.rs:100-105 fires.
Common situations: Migrating a crate from a hand-written build.rs to metabuild and forgetting to remove the old `build` key. Copy-pasting a metabuild example into a crate that already has a build script. Tooling or scaffolding templates that set both.
Related errors
- found build scripts with duplicate file stems, but all…
- invalid `package.build` file name
- metabuild package ` ` must be specified in…
- can't find library ` `, rename file to `src/lib.rs` or…
- cannot mix `proc-macro` crate type with others
AI-assisted analysis of rust-lang/cargo@eb98b54bc9 (2026-08-11).
Data as JSON: /api/errors/f29cc8fc83ef0ecb.
Report an issue: GitHub.
Appendix: source
Thrown at src/workspace/parser/targets.rs:105
targets.extend(to_test_targets(
normalized_toml.test.as_deref().unwrap_or_default(),
package_root,
edition,
warnings,
)?);
targets.extend(to_bench_targets(
normalized_toml.bench.as_deref().unwrap_or_default(),
package_root,
edition,
warnings,
)?);
// processing the custom build script
if let Some(custom_build) = package.normalized_build().expect("previously normalized") {
if metabuild.is_some() {
anyhow::bail!("cannot specify both `metabuild` and `build`");
}
validate_unique_build_scripts(custom_build)?;
for script in custom_build {
let script_path = Path::new(script);
let name = format!(
"build-script-{}",
script_path
.file_stem()
.and_then(|s| s.to_str())
.expect("previously normalized")
);
targets.push(Target::custom_build_target(
&name,
package_root.join(script_path),
edition,
));
}
}View on GitHub (pinned to eb98b54bc9)