rust-lang/cargo · error

package is a table

Error message

package is a table

What it means

Invariant in `update_manifest_with_inherited_workspace_package_keys`. It takes `manifest["package"].as_table_mut().expect("package is a table")`. The manifest being edited was just produced by `cargo new`, which always writes a `[package]` table, so the downcast should always succeed.

Source

Thrown at src/ops/cargo_new.rs:972

    Ok(())
}

// Update the manifest with the inherited workspace package keys.
// If the option is not set, the key is removed from the manifest.
// If the option is set, keep the value from the manifest.
fn update_manifest_with_inherited_workspace_package_keys(
    opts: &MkOptions<'_>,
    manifest: &mut toml_edit::DocumentMut,
    workspace_package_keys: &toml_edit::Table,
) {
    if workspace_package_keys.is_empty() {
        return;
    }

    let try_remove_and_inherit_package_key = |key: &str, manifest: &mut toml_edit::DocumentMut| {
        let package = manifest["package"]
            .as_table_mut()
            .expect("package is a table");
        package.remove(key);
        let mut table = toml_edit::Table::new();
        table.set_dotted(true);
        table["workspace"] = toml_edit::value(true);
        package.insert(key, toml_edit::Item::Table(table));
    };

    // Inherit keys from the workspace.
    // Only keep the value from the manifest if the option is set.
    for (key, _) in workspace_package_keys {
        if key == "edition" && opts.edition.is_some() {
            continue;
        }
        if key == "publish" && opts.registry.is_some() {
            continue;
        }

        try_remove_and_inherit_package_key(key, manifest);

View on GitHub (pinned to 0e07a15537)

Solutions

  1. Report a cargo bug if reproduced with stock `cargo new` inside a workspace that has `[workspace.package]` keys.
  2. Inspect the generated `Cargo.toml` before the crash — confirm `[package]` is present and tabular.
  3. If patching cargo, guard with `bail!("expected [package] table")` instead of `expect` to surface a real error.

Example fix

// before
let package = manifest["package"].as_table_mut().expect("package is a table");

// after
let package = manifest["package"].as_table_mut()
    .ok_or_else(|| anyhow::anyhow!("[package] is missing or not a table in generated manifest"))?;
Defensive patterns

Strategy: validation

Validate before calling

// Validate the generated manifest has a [package] table before workspace inheritance.
if manifest.get("package").and_then(|p| p.as_table()).is_none() {
    return Err(anyhow!("generated manifest is missing a [package] table"));
}

Prevention

When it happens

Trigger: Reachable only if the freshly-created `Cargo.toml`'s top-level `package` key is not a table — e.g. a malformed template, a `toml_edit` bug, or a code path that mutates `manifest["package"]` to a scalar before this function runs.

Common situations: Custom cargo builds that alter the package section; corrupt `cargo new` templates; extremely rare in released cargo. Real users invoking `cargo new` in a workspace never see this.

Related errors


AI-assisted analysis of rust-lang/cargo@0e07a15537 (2026-08-06). Data as JSON: /data/errors/0a7015570d368904.json. Report an issue: GitHub.