rust-lang/cargo · error · anyhow::Error
Source directory was modified by build.rs during cargo publi
Error message
Source directory was modified by build.rs during cargo publish. Build scripts should not modify anything outside of OUT_DIR.
{}
To proceed despite this, pass the `--no-verify` flag. What it means
During `cargo publish` verification, Cargo hashes every file under the unpacked source before and after running the verification build. If the hashes differ it concludes a build script or proc-macro wrote outside of OUT_DIR (typically into src/), which would make the published crate non-deterministic. It bails at verify.rs:123 unless --no-verify is passed.
Source
Thrown at src/ops/cargo_package/verify.rs:123
cli_features: opts.cli_features.clone(),
spec: ops::Packages::Packages(Vec::new()),
filter: ops::CompileFilter::Default {
required_features_filterable: true,
},
target_rustdoc_args: None,
target_rustc_args: rustc_args,
target_rustc_crate_types: None,
rustdoc_document_private_items: false,
honor_rust_version: None,
},
&exec,
)?;
// Check that `build.rs` didn't modify any files in the `src` directory.
let ws_fingerprint = hash_all(&dst)?;
if pkg_fingerprint != ws_fingerprint {
let changes = report_hash_difference(&pkg_fingerprint, &ws_fingerprint);
anyhow::bail!(
"Source directory was modified by build.rs during cargo publish. \
Build scripts should not modify anything outside of OUT_DIR.\n\
{}\n\n\
To proceed despite this, pass the `--no-verify` flag.",
changes
)
}
Ok(())
}
/// Hashes everything under a given directory.
///
/// This is for checking if any source file inside a `.crate` file has changed
/// durint the compilation. It is usually caused by bad build scripts or proc
/// macros trying to modify source files. Cargo disallows that.
fn hash_all(path: &Path) -> CargoResult<HashMap<PathBuf, u64>> {
fn wrap(path: &Path) -> CargoResult<HashMap<PathBuf, u64>> {View on GitHub (pinned to 0e07a15537)
Solutions
- Fix the build script to write only to the OUT_DIR path passed via the environment variable, and include generated code via `include!(concat!(env!("OUT_DIR"), "/generated.rs"))`.
- If the modification is benign and you accept the risk, pass `--no-verify` to `cargo publish`.
- Audit proc-macros / build deps for any that write to the crate source tree.
Example fix
// before - build.rs writes into src/
fn main() {
std::fs::write("src/generated.rs", "...").unwrap();
}
// after - write to OUT_DIR and include it
fn main() {
let out = std::env::var("OUT_DIR").unwrap();
std::fs::write(format!("{out}/generated.rs"), "...").unwrap();
}
// in lib.rs:
// include!(concat!(env!("OUT_DIR"), "/generated.rs")); Defensive patterns
Strategy: validation
Validate before calling
# Verify the source tree is unchanged after a local build:
before=$(find src -type f -exec sha256sum {} + | sha256sum)
cargo build
after=$(find src -type f -exec sha256sum {} + | sha256sum)
[ "$before" = "$after" ] || { echo "build.rs mutated src/"; exit 1; } Prevention
- Constrain build scripts to write only under OUT_DIR.
- Review proc-macro crates in your dep tree for source mutation.
- Run `cargo publish --dry-run` locally to exercise the verify step before the real publish.
When it happens
Trigger: A build.rs (or proc-macro invoked during the verify build) that writes/modifies files inside src/ or anywhere outside OUT_DIR; in-place code generators.
Common situations: Build scripts that patch source files; codegen tools that write into the crate source rather than emitting to OUT_DIR; accidental `include_str!`/codegen writing back to source.
Related errors
- cannot package a filename with a special character `{}`: {}
- {} files in the working directory contain changes that were
- found a virtual manifest at `{}` instead of a package manife
- all dependencies must have a version requirement specified w
- cannot specify both `@{v}` and `--version`
AI-assisted analysis of rust-lang/cargo@0e07a15537 (2026-08-06).
Data as JSON: /data/errors/8a7663b18517d488.json.
Report an issue: GitHub.