rust-lang/cargo · error

the manifest-path must be a path to a Cargo.toml or script…

Error message

the manifest-path must be a path to a Cargo.toml or script file: `{}`

What it means

With -Zscript enabled, a --manifest-path that exists, is not a directory, and does not end in Cargo.toml nor is an embedded script is rejected. The script feature broadens acceptance to single-file .rs scripts with embedded manifests, but arbitrary files still fail.

Solutions

  1. Point --manifest-path at a Cargo.toml, or at an .rs file whose leading comment block contains an embedded Cargo manifest.
  2. Confirm the file actually has the embedded manifest syntax cargo expects.

Example fix

# before
# cargo build --manifest-path script.txt -Zscript

# after
# rename to script.rs with embedded manifest, then:
# cargo build --manifest-path script.rs -Zscript
Defensive patterns

Strategy: validation

Validate before calling

use std::path::Path;

fn validate_script_manifest(p: &Path, script_unstable: bool) -> Result<(), String> {
    if !script_unstable {
        return Err("embedded/script manifests require -Zscript (nightly)".into());
    }
    if !(p.ends_with("Cargo.toml") || cargo::workspace::parser::is_embedded(p)) {
        return Err(format!("{p:?} is not a Cargo.toml or embedded .rs manifest"));
    }
    Ok(())
}

Prevention

When it happens

Trigger: Running `cargo <cmd> --manifest-path foo.txt -Zscript` where foo.txt is neither Cargo.toml nor a recognized embedded-manifest .rs script.

Common situations: Pointing --manifest-path at a non-manifest file expecting the script feature to accept it; wrong file extension for a single-file package.

Related errors


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

Appendix: source

Thrown at src/util/command_prelude.rs:1070

        // In general, we try to avoid normalizing paths in Cargo,
        // but in this particular case we need it to fix #3586.
        let path = paths::normalize_path(&path);
        if !path.exists() {
            anyhow::bail!("manifest path `{}` does not exist", manifest_path.display())
        } else if path.is_dir() {
            let child_path = path.join("Cargo.toml");
            let suggested_path = if child_path.exists() {
                format!("\nhelp: {} exists", child_path.display())
            } else {
                "".to_string()
            };
            anyhow::bail!(
                "manifest path `{}` is a directory but expected a file{suggested_path}",
                manifest_path.display()
            )
        } else if !path.ends_with("Cargo.toml") && !crate::workspace::parser::is_embedded(&path) {
            if gctx.cli_unstable().script {
                anyhow::bail!(
                    "the manifest-path must be a path to a Cargo.toml or script file: `{}`",
                    path.display()
                )
            } else {
                anyhow::bail!(
                    "the manifest-path must be a path to a Cargo.toml file: `{}`",
                    path.display()
                )
            }
        }
        if crate::workspace::parser::is_embedded(&path) && !gctx.cli_unstable().script {
            anyhow::bail!("embedded manifest `{}` requires `-Zscript`", path.display())
        }
        Ok(path)
    } else {
        find_root_manifest_for_wd(gctx.cwd())
    }
}

View on GitHub (pinned to 98a09e7e7d)