rust-lang/cargo · error · anyhow::Error

--exclude can only be used together with --workspace

Error message

--exclude can only be used together with --workspace

What it means

Thrown by Packages::from_flags (src/ops/cargo_compile/packages.rs:35-43) when the `--exclude` flag is passed without `--workspace` (or `-r`/`--all`). Exclusion only has meaning over the full workspace set, so Cargo rejects exclude used in isolation.

Source

Thrown at src/ops/cargo_compile/packages.rs:39

    ///
    /// As of the time of this writing, it only works on opting in all workspace members.
    /// Keeps the packages passed in to verify that they exist in the workspace.
    All(Vec<String>),
    /// Opt out of packages passed in.
    ///
    /// As of the time of this writing, it only works on opting out workspace members.
    OptOut(Vec<String>),
    /// A sequence of hand-picked packages that will be built. Normally done by `-p` flag.
    Packages(Vec<String>),
}

impl Packages {
    /// Creates a `Packages` from flags which are generally equivalent to command line flags.
    pub fn from_flags(all: bool, exclude: Vec<String>, package: Vec<String>) -> CargoResult<Self> {
        Ok(match (all, exclude.len(), package.len()) {
            (false, 0, 0) => Packages::Default,
            (false, 0, _) => Packages::Packages(package),
            (false, _, _) => anyhow::bail!("--exclude can only be used together with --workspace"),
            (true, 0, _) => Packages::All(package),
            (true, _, _) => Packages::OptOut(exclude),
        })
    }

    /// Converts selected packages to [`PackageIdSpec`]s.
    pub fn to_package_id_specs(&self, ws: &Workspace<'_>) -> CargoResult<Vec<PackageIdSpec>> {
        let specs = match self {
            Packages::All(packages) => {
                emit_packages_not_found_within_workspace(ws, packages)?;
                ws.members()
                    .map(Package::package_id)
                    .map(|id| id.to_spec())
                    .collect()
            }
            Packages::OptOut(opt_out) => {
                let (mut patterns, mut ids) = opt_patterns_and_ids(opt_out)?;
                let specs = ws

View on GitHub (pinned to 0e07a15537)

Solutions

  1. Add --workspace: `cargo build --workspace --exclude foo`.
  2. If you only want specific packages, drop --exclude and use `-p a -p b` to list what you want.
  3. Remove the --exclude flag entirely.

Example fix

# before
cargo test --exclude slow-crate

# after
cargo test --workspace --exclude slow-crate
Defensive patterns

Strategy: validation

Validate before calling

// Packages::from_flags requires: exclude.is_empty() || all == true.
use cargo::ops::Packages;

fn validate_flags(all: bool, exclude: &[String], package: &[String])
    -> Result<Packages, String>
{
    if !exclude.is_empty() && !all {
        return Err("--exclude requires --workspace".into());
    }
    Packages::from_flags(all, exclude.to_vec(), package.to_vec())
        .map_err(|e| e.to_string())
}

Type guard

fn exclude_is_valid(all: bool, exclude: &[String]) -> bool {
    exclude.is_empty() || all
}

Try / catch

match Packages::from_flags(all, exclude, package) {
    Err(e) if e.to_string().contains("--exclude") => {
        eprintln!("add --workspace when using --exclude");
        return Err(e);
    }
    r => r,
}

Prevention

When it happens

Trigger: Invoking `cargo build --exclude foo` (or test/check/etc.) without also passing --workspace/--all. The match arm `(false, _, _)` where exclude.len() > 0 bails.

Common situations: Copy-pasting a command that used --exclude from a workspace context into a non-workspace invocation. Muscle-memory `--exclude` forgetting the companion --workspace. Aliases or scripts that inject --exclude conditionally.

Related errors


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