rust-lang/cargo · error

Source directory was modified by build.rs during cargo…

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

Thrown during the verification step of `cargo publish` when a build script (`build.rs`) modifies files inside the `src` directory. Cargo fingerprints the source tree before and after compilation; a hash mismatch means the build script wrote outside its designated `OUT_DIR`, which could corrupt the published crate. The `--no-verify` flag skips this check.

Solutions

  1. Fix the build script to write generated files exclusively to `$OUT_DIR` (the directory passed to build scripts).
  2. Fix proc macros to not emit files into the source tree.
  3. Pass `--no-verify` to bypass the check if the modification is intentional and safe: `cargo publish --no-verify`.

Example fix

// build.rs (before — writes to src/)
fn main() {
    std::fs::write("src/generated.rs", "// ...").unwrap();
}

// build.rs (after — writes to OUT_DIR)
fn main() {
    let out_dir = std::env::var("OUT_DIR").unwrap();
    std::fs::write(
        std::path::Path::new(&out_dir).join("generated.rs"),
        "// ...",
    ).unwrap();
}
Defensive patterns

Strategy: validation

Validate before calling

// Verify build script only writes to OUT_DIR
// In build.rs, always use:
fn main() {
    let out_dir = std::env::var("OUT_DIR").expect("OUT_DIR not set");
    // Only write under out_dir
    let path = std::path::Path::new(&out_dir).join("generated.rs");
    std::fs::write(&path, "// generated").unwrap();
    println!("cargo:rerun-if-changed=some_input.txt");
}

Prevention

When it happens

Trigger: Running `cargo publish` (without `--no-verify`) on a crate whose `build.rs` or a proc-macro invoked during compilation writes to, creates, or deletes files under `src/`. The `hash_all(&dst)` comparison detects any change.

Common situations: Build scripts that generate code into `src/` instead of `OUT_DIR`; proc macros that emit files next to source; buggy or malicious build scripts; code generators writing to tracked source paths.

Related errors


AI-assisted analysis of rust-lang/cargo@eb98b54bc9 (2026-08-11). Data as JSON: /api/errors/76ec12e7f02df424. Report an issue: GitHub.

Appendix: 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 eb98b54bc9)