rust-lang/cargo · error
has_custom_build should have RunCustomBuild
Error message
has_custom_build should have RunCustomBuild
What it means
When a package has a custom build script (`unit.pkg.has_custom_build()`), Cargo fetches its link metadata via `find_build_script_metadatas(unit).expect("has_custom_build should have RunCustomBuild")`. The expect encodes the invariant that a package flagged as having a build script always has a corresponding `RunCustomBuild` unit whose metadata can be located. Failure means `has_custom_build()` and the unit/metadata bookkeeping disagree.
Source
Thrown at src/compiler/custom_build.rs:1320
if let Some(links) = unit.pkg.manifest().links() {
if let Some(output) = unit.links_overrides.get(links) {
let metadata = build_runner.get_run_build_script_metadata(unit);
build_runner.build_script_outputs.lock().unwrap().insert(
unit.pkg.package_id(),
metadata,
output.clone(),
);
}
}
}
let mut ret = BuildScripts::default();
// If a package has a build script, add itself as something to inspect for linking.
if !unit.target.is_custom_build() && unit.pkg.has_custom_build() {
let script_metas = build_runner
.find_build_script_metadatas(unit)
.expect("has_custom_build should have RunCustomBuild");
for script_meta in script_metas {
add_to_link(&mut ret, unit.pkg.package_id(), script_meta);
}
}
if unit.mode.is_run_custom_build() {
parse_previous_explicit_deps(build_runner, unit);
}
// We want to invoke the compiler deterministically to be cache-friendly
// to rustc invocation caching schemes, so be sure to generate the same
// set of build script dependency orderings via sorting the targets that
// come out of the `Context`.
let mut dependencies: Vec<Unit> = build_runner
.unit_deps(unit)
.iter()
.map(|d| d.unit.clone())
.collect();View on GitHub (pinned to 0e07a15537)
Solutions
- `cargo clean` and rebuild to regenerate build-script metadata.
- Ensure only one Cargo version operates on a given `target/` dir.
- If reproducible, report upstream with the minimal `Cargo.toml` that has a `build.rs`.
Example fix
// before
let script_metas = build_runner
.find_build_script_metadatas(unit)
.expect("has_custom_build should have RunCustomBuild");
// after
let script_metas = build_runner
.find_build_script_metadatas(unit)
.with_context(|| format!("package `{}` flagged has_custom_build but its RunCustomBuild metadata is missing", unit.pkg.package_id()))?; Defensive patterns
Strategy: validation
Validate before calling
// (cargo-internal) before reading link metadata, confirm a RunCustomBuild unit exists for the pkg: // assert!(build_runner.unit_graph.iter().any(|(u, _)| u.pkg == unit.pkg && u.mode.is_run_custom_build()));
Prevention
- `cargo clean` to regenerate build-script metadata.
- Keep one Cargo version per target dir.
- Run `cargo clean` after renaming/removing a `build.rs`.
When it happens
Trigger: A package whose `Cargo.toml` declares `build = ...` (so `has_custom_build` is true) but whose unit graph lacks the `RunCustomBuild` unit, or whose `find_build_script_metadatas` returns `Err`; inconsistent state between `Package` metadata and the compiled build-script outputs.
Common situations: Interrupted build leaving `target/` with stale metadata; Cargo version mismatch between who wrote `target/` and who is reading it; metabuild/`build.rs` rename without `cargo clean`.
Related errors
- running a script not depending on an actual script
- output must exist after running
- metadata version {} not supported, only {} is currently supp
- required(true)
- a file should always have a parent
AI-assisted analysis of rust-lang/cargo@0e07a15537 (2026-08-06).
Data as JSON: /data/errors/9820f31c9076391e.json.
Report an issue: GitHub.