rust-lang/cargo · error

invalid inclusion of reserved file name

Error message

invalid inclusion of reserved file name {} in package source

What it means

During `cargo package`, cargo walks every source file to archive it. Two filenames are reserved and must NEVER come from the package's own source: `Cargo.toml.orig` (cargo writes the original manifest under this name itself) and `.cargo_vcs_info.json` (cargo generates this from VCS metadata). If either appears in the user's source tree, packaging aborts — including it would either be overwritten by cargo's generated copy (losing data) or spoof cargo's integrity metadata.

Solutions

  1. Delete the offending reserved file(s) from the source tree: `rm Cargo.toml.orig .cargo_vcs_info.json` (and add them to `.gitignore`).
  2. Ensure no build/generation step writes these filenames into the package source.
  3. If you extracted a published crate to study/modify it, remove the packaging metadata before re-packaging.

Example fix

# before
$ ls
Cargo.toml.orig  .cargo_vcs_info.json  Cargo.toml  src/
$ cargo package   # error: invalid inclusion of reserved file name

# after
$ rm Cargo.toml.orig .cargo_vcs_info.json
$ cargo package
Defensive patterns

Strategy: validation

Validate before calling

use std::path::Path;
const RESERVED: &[&str] = &["Cargo.toml.orig", ".cargo_vcs_info.json"];
fn contains_reserved_source_file(root: &Path) -> Vec<String> {
    RESERVED.iter().filter(|n| root.join(n).exists()).map(|s| s.to_string()).collect()
}
// before `cargo package`, if !contains_reserved_source_file(&root).is_empty() { remove them }

Type guard

fn is_packaging_clean(root: &Path) -> bool { contains_reserved_source_file(root).is_empty() }

Prevention

When it happens

Trigger: Running `cargo package` when the package source tree contains a file literally named `Cargo.toml.orig` or `.cargo_vcs_info.json` — e.g. left over from unzipping a previously packaged `.crate`, or committed by mistake after extracting a published crate.

Common situations: Unpacking a downloaded `.crate` (which contains both reserved files) and then re-packaging without removing them. Copying a `target/package/` output back into source. A build script or generator that emits `Cargo.toml.orig`. Accidental commit of packaging artifacts.

Related errors


AI-assisted analysis of rust-lang/cargo@495c385d08 (2026-08-11). Data as JSON: /api/errors/40750f304921ad98. Report an issue: GitHub.

Appendix: source

Thrown at src/ops/cargo_package/mod.rs:515

#[tracing::instrument(skip_all)]
fn build_ar_list(
    ws: &Workspace<'_>,
    pkg: &Package,
    src_files: Vec<PathEntry>,
    vcs_info: Option<vcs::VcsInfo>,
    include_lockfile: bool,
) -> CargoResult<Vec<ArchiveFile>> {
    let mut result = HashMap::default();
    let root = pkg.root();
    for src_file in &src_files {
        let rel_path = src_file.strip_prefix(&root)?;
        check_filename(rel_path, &mut ws.gctx().shell())?;
        let rel_str = rel_path.to_str().ok_or_else(|| {
            anyhow::format_err!("non-utf8 path in source directory: {}", rel_path.display())
        })?;
        match rel_str {
            "Cargo.lock" => continue,
            VCS_INFO_FILE | ORIGINAL_MANIFEST_FILE => anyhow::bail!(
                "invalid inclusion of reserved file name {} in package source",
                rel_str
            ),
            _ => {
                result
                    .entry(UncasedAscii::new(rel_str))
                    .or_insert_with(Vec::new)
                    .push(ArchiveFile {
                        rel_path: rel_path.to_owned(),
                        rel_str: rel_str.to_owned(),
                        contents: FileContents::OnDisk(src_file.to_path_buf()),
                    });
            }
        }
    }

    // Ensure we normalize for case insensitive filesystems (like on Windows) by removing the
    // existing entry, regardless of case, and adding in with the correct case

View on GitHub (pinned to 495c385d08)