{"id":"aa8d2f9c3efdf1e2","repo":"rust-lang/cargo","slug":"can-t-specify-both-lib-and-binary-outputs","errorCode":null,"errorMessage":"can't specify both lib and binary outputs","messagePattern":"can't specify both lib and binary outputs","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src/ops/cargo_new.rs","lineNumber":116,"sourceCode":"    source_files: Vec<SourceFileInformation>,\n    edition: Option<&'a str>,\n    registry: Option<&'a str>,\n}\n\nimpl NewOptions {\n    pub fn new(\n        version_control: Option<VersionControl>,\n        bin: bool,\n        lib: bool,\n        path: PathBuf,\n        name: Option<String>,\n        edition: Option<String>,\n        registry: Option<String>,\n    ) -> CargoResult<NewOptions> {\n        let auto_detect_kind = !bin && !lib;\n\n        let kind = match (bin, lib) {\n            (true, true) => anyhow::bail!(\"can't specify both lib and binary outputs\"),\n            (false, true) => NewProjectKind::Lib,\n            (_, false) => NewProjectKind::Bin,\n        };\n\n        let opts = NewOptions {\n            version_control,\n            kind,\n            auto_detect_kind,\n            path,\n            name,\n            edition,\n            registry,\n        };\n        Ok(opts)\n    }\n}\n\n#[derive(Deserialize)]","sourceCodeStart":98,"sourceCodeEnd":134,"githubUrl":"https://github.com/rust-lang/cargo/blob/0e07a155371a6ce88ae53a2c00df940280c09a67/src/ops/cargo_new.rs#L98-L134","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Decide the primary target and pass only one flag: `cargo new --lib myproj` or `cargo new --bin myproj`","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","Drop both flags; Cargo defaults to --bin"],"exampleFix":"# before\ncargo new --bin --lib myproj\n# after\ncargo new --lib myproj   # then later add src/bin/myproj.rs if a binary is needed","handlingStrategy":"validation","validationCode":"fn validate_new_flags(bin: bool, lib: bool) -> Result<(), String> {\n    if bin && lib {\n        return Err(\"pass at most one of --bin/--lib\".into());\n    }\n    Ok(())\n}\n\nvalidate_new_flags(opts.bin, opts.lib)?;","typeGuard":"type NewKind = 'bin' | 'lib' | 'auto';\nfunction resolveKind(bin: boolean, lib: boolean): NewKind {\n  if (bin && lib) throw new Error('mutually exclusive');\n  return bin ? 'bin' : lib ? 'lib' : 'auto';\n}","tryCatchPattern":null,"preventionTips":["Treat --bin/--lib as a single enum (auto|bin|lib) instead of two booleans in wrapper scripts","In CI, lint cargo invocations that pass both flags","Document that `cargo new` defaults to --bin so neither flag is usually needed"],"tags":["cargo-new","cli-args","validation"],"analyzedSha":"0e07a155371a6ce88ae53a2c00df940280c09a67","analyzedAt":"2026-08-06T01:46:58.334Z","schemaVersion":2}