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

  1. Verify the file referenced by `license-file` or `readme` in Cargo.toml exists at the stated relative path from the package root.
  2. Correct the path in Cargo.toml to match the actual filename (case-sensitive on Unix).
  3. Remove the `license-file`/`readme` key from Cargo.toml if the file is no longer relevant.
  4. 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

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


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)