{"record":{"id":"8d38e082f73ec34f","repo":"rust-lang/cargo","slug":"cannot-have-a-package-with-multiple-libraries-fou","errorCode":null,"errorMessage":"cannot have a package with multiple libraries, found both `{}` and `{}`","messagePattern":"cannot have a package with multiple libraries, found both `(.+?)` and `(.+?)`","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/ops/cargo_new.rs","lineNumber":355,"sourceCode":"    let mut duplicates_checker: BTreeMap<&str, &SourceFileInformation> = BTreeMap::new();\n\n    for i in detected_files {\n        if i.bin {\n            if let Some(x) = BTreeMap::get::<str>(&duplicates_checker, &name) {\n                anyhow::bail!(\n                    \"\\\nmultiple possible binary sources found:\n  {}\n  {}\ncannot automatically generate Cargo.toml as the main target would be ambiguous\",\n                    &x.relative_path,\n                    &i.relative_path\n                );\n            }\n            duplicates_checker.insert(name, i);\n        } else {\n            if let Some(plp) = previous_lib_relpath {\n                anyhow::bail!(\n                    \"cannot have a package with \\\n                     multiple libraries, \\\n                     found both `{}` and `{}`\",\n                    plp,\n                    i.relative_path\n                )\n            }\n            previous_lib_relpath = Some(&i.relative_path);\n        }\n    }\n\n    Ok(())\n}\n\nfn plan_new_source_file(bin: bool) -> SourceFileInformation {\n    if bin {\n        SourceFileInformation {\n            relative_path: \"src/main.rs\".to_string(),","sourceCodeStart":337,"sourceCodeEnd":373,"githubUrl":"https://github.com/rust-lang/cargo/blob/98a09e7e7d62850f14e5b6132101fc1edd19a16f/src/ops/cargo_new.rs#L337-L373","documentation":"Inside `detect_source_paths_and_types`, if more than one file is detected as a library source (e.g. both `src/lib.rs` and `lib.rs`, or `src/<name>.rs` lib-detections), cargo refuses: a package may have at most one library target. `previous_lib_relpath` tracks the first lib; a second triggers the bail naming both relative paths.","triggerScenarios":"`cargo init` in a directory containing both `src/lib.rs` and `lib.rs`, or multiple files that the detection rules classify as library roots.","commonSituations":"Migrating a project that keeps lib sources in two locations. Leftover files from a refactor. Copying a library crate's contents into a directory that already has a `src/lib.rs`.","solutions":["Keep exactly one library root — conventionally `src/lib.rs` — and remove/relocate the other.","If the second file is a module, move it under `src/` (e.g. `src/extra.rs`) and `mod extra;` rather than leaving it as a stray lib root.","Re-run `cargo init` once the layout has a single lib."],"exampleFix":"# before — directory has both:\n#   ./lib.rs\n#   ./src/lib.rs\n$ cargo init   # error: multiple libraries\n\n# after\n$ rm lib.rs\n$ cargo init","handlingStrategy":"validation","validationCode":"// Before `cargo init`, ensure at most one library root exists.\nfn count_lib_sources(files: &[&str]) -> usize {\n    files.iter().filter(|f| matches!(**f, \"src/lib.rs\" | \"lib.rs\")).count()\n}\n// if count_lib_sources(&files) > 1 { ask user to consolidate }","typeGuard":"fn has_unique_lib_root(files: &[&str]) -> bool { count_lib_sources(&files) <= 1 }","tryCatchPattern":null,"preventionTips":["Keep a single `src/lib.rs` as the library root.","Move auxiliary code into modules under `src/` rather than extra lib roots.","Pre-scan during migration to catch duplicate lib files."],"tags":["cargo-init","source-detection","library-targets","migration"],"backgroundTag":null,"analyzedSha":"98a09e7e7d62850f14e5b6132101fc1edd19a16f","analyzedAt":"2026-08-11T17:42:36.556Z","contentChangedAt":"2026-08-11T17:42:36.556Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}