rust-lang/cargo · error
{}
Error message
{} What it means
Thrown during `cargo package` or `cargo publish` when manifest metadata fields (`license-file` or `readme`) point to files that do not exist on disk. The `error_on_nonexistent_file` helper accumulates one message per missing file into `invalid_manifest_field`, and this bail joins them with newlines. The `{}` placeholder is filled by the concatenated per-field error strings.
Solutions
- Verify the file referenced by `license-file` or `readme` in Cargo.toml exists at the stated relative path from the package root.
- Correct the path in Cargo.toml to match the actual filename (case-sensitive on Unix).
- Remove the `license-file`/`readme` key from Cargo.toml if the file is no longer relevant.
- Re-create the missing file if it was accidentally deleted.
Example fix
// Cargo.toml (before) license-file = "LICENCE" readme = "README.markdown" // Cargo.toml (after — match actual filenames) license-file = "LICENSE" readme = "README.md"
Defensive patterns
Strategy: validation
Validate before calling
// Before calling cargo package, verify referenced files exist
use std::path::Path;
fn validate_manifest_files(pkg_root: &Path, license_file: Option<&str>, readme: Option<&str>) -> Result<(), String> {
let mut errs = Vec::new();
if let Some(lf) = license_file {
if !pkg_root.join(lf).is_file() { errs.push(format!("license-file `{}` not found", lf)); }
}
if let Some(rm) = readme {
if !pkg_root.join(rm).is_file() { errs.push(format!("readme `{}` not found", rm)); }
}
if errs.is_empty() { Ok(()) } else { Err(errs.join("\n")) }
} Prevention
- Run `cargo package --no-verify --list` as a pre-publish smoke test to catch missing files early.
- Keep LICENSE and README filenames consistent across all crates in a workspace.
- Use CI to run `cargo publish --dry-run` before merging to main.
When it happens
Trigger: Calling `cargo package` or `cargo publish` on a crate whose `Cargo.toml` declares `license-file = "LICENSE"` or `readme = "README.md"` but the referenced file does not exist at the resolved path (relative to the package root). Both fields are checked sequentially; if both are missing, two messages are joined.
Common situations: Renaming or deleting a LICENSE/README file without updating Cargo.toml; typos in the path value; using an absolute path that works on one developer's machine but not another; restructuring a project and forgetting to update manifest metadata.
Related errors
- This may cause issue during packaging, as modules…
- all dependencies must have a version requirement specified…
- can only edit absolute paths, got
- can't find library ` `, rename file to `src/lib.rs` or…
- cannot mix `proc-macro` crate type with others
AI-assisted analysis of rust-lang/cargo@495c385d08 (2026-08-11).
Data as JSON: /api/errors/6a61de8fe75f89ce.
Report an issue: GitHub.
Appendix: source
Thrown at src/ops/cargo_package/mod.rs:621
&pkg,
&license_path,
"license-file",
&mut invalid_manifest_field,
);
}
}
if let Some(readme) = &pkg.manifest().metadata().readme {
let readme_path = Path::new(readme);
let abs_file_path = paths::normalize_path(&pkg.root().join(readme_path));
if abs_file_path.is_file() {
check_for_file_and_add("readme", readme_path, abs_file_path, pkg, &mut result, ws)?;
} else {
error_on_nonexistent_file(&pkg, &readme_path, "readme", &mut invalid_manifest_field);
}
}
if !invalid_manifest_field.is_empty() {
return Err(anyhow::anyhow!(invalid_manifest_field.join("\n")));
}
for t in pkg
.manifest()
.targets()
.iter()
.filter(|t| t.is_custom_build())
{
if let Some(custom_build_path) = t.src_path().path() {
let abs_custom_build_path = paths::normalize_path(&pkg.root().join(custom_build_path));
if !abs_custom_build_path.is_file() || !abs_custom_build_path.starts_with(pkg.root()) {
error_custom_build_file_not_in_package(pkg, &abs_custom_build_path, t)?;
}
}
}
result.sort_unstable_by(|a, b| a.rel_path.cmp(&b.rel_path));
View on GitHub (pinned to 495c385d08)