{"id":"bbea9adecf0f7465","repo":"rust-lang/cargo","slug":"invalid-character-in-dependency-name-toolc","errorCode":null,"errorMessage":"invalid character `+` in dependency name: `+{toolchain}`\n    Use `cargo +{toolchain} add` if you meant to use the `{toolchain}` toolchain.","messagePattern":"invalid character `\\+` in dependency name: `\\+(.+?)`\n    Use `cargo \\+(.+?) add` if you meant to use the `(.+?)` toolchain\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/bin/cargo/commands/add.rs","lineNumber":266,"sourceCode":"    };\n    let default_features = default_features(matches);\n    let optional = optional(matches);\n    let public = public(matches);\n\n    let mut crates = matches\n        .get_many::<String>(\"crates\")\n        .into_iter()\n        .flatten()\n        .map(|c| (Some(c.clone()), None))\n        .collect::<IndexMap<_, _>>();\n\n    let mut infer_crate_name = false;\n\n    for (crate_name, _) in crates.iter() {\n        let crate_name = crate_name.as_ref().unwrap();\n\n        if let Some(toolchain) = crate_name.strip_prefix(\"+\") {\n            anyhow::bail!(\n                \"invalid character `+` in dependency name: `+{toolchain}`\n    Use `cargo +{toolchain} add` if you meant to use the `{toolchain}` toolchain.\"\n            );\n        }\n    }\n\n    if crates.is_empty() {\n        if path.is_some() || git.is_some() {\n            crates.insert(None, None);\n            infer_crate_name = true;\n        } else {\n            unreachable!(\"clap should ensure we have some source selected\");\n        }\n    }\n    for feature in matches\n        .get_many::<String>(\"features\")\n        .into_iter()\n        .flatten()","sourceCodeStart":248,"sourceCodeEnd":284,"githubUrl":"https://github.com/rust-lang/cargo/blob/0e07a155371a6ce88ae53a2c00df940280c09a67/src/bin/cargo/commands/add.rs#L248-L284","documentation":"From parse_dependencies (src/bin/cargo/commands/add.rs:265-270). For each crate name passed to `cargo add`, if it begins with `+`, Cargo assumes the user confused a toolchain override with a dependency and bails, suggesting the correct `cargo +<toolchain> add` form. The `+` prefix is reserved by Cargo itself for toolchain selection.","triggerScenarios":"Running `cargo add +nightly serde` instead of `cargo +nightly add serde`. Copying a toolchain-prefixed command and appending `add <crate>` in the wrong position.","commonSituations":"Misremembering argument order for toolchain overrides; shell scripts that concatenate `+toolchain` with the subcommand incorrectly; onboarding from a doc snippet with the wrong order.","solutions":["Move the toolchain before the subcommand: `cargo +<toolchain> add <crate>`.","If you did not mean a toolchain, remove the leading `+` from the dependency name.","Double-check shell quoting isn't prepending a stray `+`."],"exampleFix":"// before\ncargo add +nightly serde\n\n// after\ncargo +nightly add serde","handlingStrategy":"validation","validationCode":"// Normalize a toolchain+add invocation: ensure `+toolchain` precedes the subcommand\nfn build_add_cmd(toolchain: Option<&str>, crate_name: &str) -> Vec<String> {\n    let mut v: Vec<String> = vec![\"cargo\".into()];\n    if let Some(tc) = toolchain.filter(|t| !t.is_empty()) {\n        v.push(format!(\"+{tc}\"));\n    }\n    v.push(\"add\".into());\n    assert!(!crate_name.starts_with('+'), \"crate name must not start with +\");\n    v.push(crate_name.into());\n    v\n}","typeGuard":"fn looks_like_toolchain_override(arg: &str) -> bool {\n    arg.starts_with('+') && arg.len() > 1\n}","tryCatchPattern":null,"preventionTips":["Remember the order: `cargo +toolchain <subcommand>` — the `+` always comes first.","In scripts, build the command vector with the toolchain slot before the subcommand."],"tags":["cargo","add","toolchain","cli","argument-parsing"],"analyzedSha":"0e07a155371a6ce88ae53a2c00df940280c09a67","analyzedAt":"2026-08-06T01:46:58.334Z","schemaVersion":2}