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

can't specify both lib and binary outputs

Error message

can't specify both lib and binary outputs

What it means

Returned by NewOptions::new when the caller passes both --bin and --lib simultaneously. A single Cargo package cannot be both a binary-only application crate and a library crate from the new() entrypoint's perspective (the flags are mutually exclusive at the CLI level), so Cargo rejects the contradiction before any files are created.

Source

Thrown at src/ops/cargo_new.rs:116

    source_files: Vec<SourceFileInformation>,
    edition: Option<&'a str>,
    registry: Option<&'a str>,
}

impl NewOptions {
    pub fn new(
        version_control: Option<VersionControl>,
        bin: bool,
        lib: bool,
        path: PathBuf,
        name: Option<String>,
        edition: Option<String>,
        registry: Option<String>,
    ) -> CargoResult<NewOptions> {
        let auto_detect_kind = !bin && !lib;

        let kind = match (bin, lib) {
            (true, true) => anyhow::bail!("can't specify both lib and binary outputs"),
            (false, true) => NewProjectKind::Lib,
            (_, false) => NewProjectKind::Bin,
        };

        let opts = NewOptions {
            version_control,
            kind,
            auto_detect_kind,
            path,
            name,
            edition,
            registry,
        };
        Ok(opts)
    }
}

#[derive(Deserialize)]

View on GitHub (pinned to 0e07a15537)

Solutions

  1. Decide the primary target and pass only one flag: `cargo new --lib myproj` or `cargo new --bin myproj`
  2. If you genuinely need both a lib and a bin in one package, create it as a lib then manually add src/main.rs plus a [[bin]] target in Cargo.toml
  3. Drop both flags; Cargo defaults to --bin

Example fix

# before
cargo new --bin --lib myproj
# after
cargo new --lib myproj   # then later add src/bin/myproj.rs if a binary is needed
Defensive patterns

Strategy: validation

Validate before calling

fn validate_new_flags(bin: bool, lib: bool) -> Result<(), String> {
    if bin && lib {
        return Err("pass at most one of --bin/--lib".into());
    }
    Ok(())
}

validate_new_flags(opts.bin, opts.lib)?;

Type guard

type NewKind = 'bin' | 'lib' | 'auto';
function resolveKind(bin: boolean, lib: boolean): NewKind {
  if (bin && lib) throw new Error('mutually exclusive');
  return bin ? 'bin' : lib ? 'lib' : 'auto';
}

Prevention

When it happens

Trigger: Invoking `cargo new --bin --lib myproj` (or the programmatic equivalent NewOptions::new with bin=true and lib=true). The match arm at cargo_new.rs:115-119 catches (true, true).

Common situations: User pastes a cargo invocation assembled from multiple examples and accidentally keeps both flags; shell aliases/scripts that unconditionally add flags; misunderstanding that a crate can contain both src/lib.rs and src/main.rs after creation but `cargo new` only scaffolds one target type.

Related errors


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