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 when an --exclude list is supplied but the `all` (i.e. --workspace) flag is false. Exclusion is only meaningful across the whole workspace, so cargo rejects it in any other selection mode.

Solutions

  1. Add --workspace (or --all) alongside --exclude.
  2. If you meant to exclude by default, restructure workspace `default-members` instead.
  3. Use -p with explicit members rather than --exclude if you do not want --workspace.

Example fix

# before
cargo build --exclude foo
# after
cargo build --workspace --exclude foo
Defensive patterns

Strategy: validation

Validate before calling

// Validate flag combination before calling Packages::from_flags.
fn valid(exclude: &[String], all: bool) -> bool { exclude.is_empty() || all }

Prevention

When it happens

Trigger: Running `cargo build --exclude foo` without also passing --workspace (or its aliases -all). Also via programmatic Packages::from_flags(false, non_empty, n).

Common situations: Cargo CLI invocations / scripts that add --exclude expecting it to filter default members; wrappers that pass exclude unconditionally.

Related errors


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

Appendix: 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 eb98b54bc9)