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
- Delete the offending reserved file(s) from the source tree: `rm Cargo.toml.orig .cargo_vcs_info.json` (and add them to `.gitignore`).
- Ensure no build/generation step writes these filenames into the package source.
- 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
- Never commit `Cargo.toml.orig` or `.cargo_vcs_info.json` into source — they are packaging outputs.
- Add both to `.gitignore`.
- After extracting a published `.crate` to modify it, delete these metadata files before re-packaging.
- Audit generators/build scripts to ensure none write these filenames into the source tree.
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
- all dependencies must have a version requirement specified…
- cannot package a filename with a special character
- {}
- files in the working directory contain changes that were…
- path does not have a unicode filename which may not unpack…
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 caseView on GitHub (pinned to 495c385d08)