rust-lang/cargo · error

not allowed in embedded manifests

Error message

{fields} {are} not allowed in embedded manifests

What it means

Thrown when validating an embedded (single-file script) manifest that contains package fields forbidden in embedded contexts. The forbidden fields include package.workspace, package.build, package.metabuild, package.links, package.autolib/autobins/autoexamples/autotests/autobenches, and package.default-run. Embedded scripts have constrained semantics (no custom build, no auto-discovery), so these fields are collected into invalid_fields and reported with proper is/are agreement.

Solutions

  1. Remove all forbidden fields from the embedded manifest's frontmatter package table.
  2. If you need build scripts, autodiscovery, or workspace links, use a traditional multi-file Cargo project instead of an embedded script.
  3. Move default-run and workspace declarations to a real Cargo.toml [package] section.

Example fix

// before (script.rs frontmatter)
//! ```cargo
//! [package]
//! name = "x"
//! build = "build.rs"
//! ```

// after
//! ```cargo
//! [package]
//! name = "x"
//! ```
Defensive patterns

Strategy: validation

Validate before calling

const FORBIDDEN_EMBEDDED: &[&str] = &[
    "workspace","build","metabuild","links","autolib",
    "autobins","autoexamples","autotests","autobenches","default-run",
];
fn check_embedded_package(pkg: &toml::Value) -> Result<(), String> {
    let bad: Vec<&&str> = FORBIDDEN_EMBEDDED.iter()
        .filter(|k| pkg.get(**k).is_some())
        .collect();
    if bad.is_empty() { Ok(()) } else { Err(format!("forbidden in embedded manifest: {}", bad.join(", "))) }
}

Type guard

fn embedded_pkg_has_forbidden_fields(pkg: &toml::value::Table) -> bool {
    ["workspace","build","metabuild","links","autolib","autobins","autoexamples","autotests","autobenches","default-run"]
        .iter().any(|k| pkg.contains_key(*k))
}

Prevention

When it happens

Trigger: A single-file cargo script (.rs with frontmatter) whose frontmatter package table includes e.g. build = "build.rs" or default-run = "x". During to_real_manifest the is_embedded branch builds the invalid_fields list and bails if non-empty.

Common situations: A developer copies fields from a regular Cargo.toml into a script's frontmatter. Using workspace inheritance inside an embedded script. Specifying a custom build script in a single-file context where it cannot apply.

Related errors


AI-assisted analysis of rust-lang/cargo@98a09e7e7d (2026-08-11). Data as JSON: /api/errors/51fe6b79aecc5d32. Report an issue: GitHub.

Appendix: source

Thrown at src/workspace/parser/mod.rs:1503

                ("`package.autobins`", autobins.is_some()),
                ("`package.autoexamples`", autoexamples.is_some()),
                ("`package.autotests`", autotests.is_some()),
                ("`package.autobenches`", autobenches.is_some()),
                ("`package.default-run`", default_run.is_some()),
            ]);
        }
        let invalid_fields = invalid_fields
            .into_iter()
            .filter_map(|(name, invalid)| invalid.then_some(name))
            .collect::<Vec<_>>();
        if !invalid_fields.is_empty() {
            let fields = invalid_fields.join(", ");
            let are = if invalid_fields.len() == 1 {
                "is"
            } else {
                "are"
            };
            anyhow::bail!("{fields} {are} not allowed in embedded manifests")
        }
    }

    let resolve_behavior = match (
        normalized_package.resolver.as_ref(),
        normalized_toml
            .workspace
            .as_ref()
            .and_then(|ws| ws.resolver.as_ref()),
    ) {
        (None, None) => None,
        (Some(s), None) | (None, Some(s)) => Some(ResolveBehavior::from_manifest(s)?),
        (Some(_), Some(_)) => {
            bail!("cannot specify `resolver` field in both `[workspace]` and `[package]`")
        }
    };

    // If we have no lib at all, use the inferred lib, if available.

View on GitHub (pinned to 98a09e7e7d)