{"id":"4b622d7284ce129b","repo":"rust-lang/cargo","slug":"package-cannot-be-tested-because-it-requires","errorCode":null,"errorMessage":"package `{}` cannot be tested because it requires dev-dependencies and is not a member of the workspace","messagePattern":"package `(.+?)` cannot be tested because it requires dev-dependencies and is not a member of the workspace","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src/ops/cargo_compile/mod.rs","lineNumber":377,"sourceCode":"    let to_build_ids = resolve.specs_to_ids(&specs)?;\n    // Now get the `Package` for each `PackageId`. This may trigger a download\n    // if the user specified `-p` for a dependency that is not downloaded.\n    // Dependencies will be downloaded during build_unit_dependencies.\n    let mut to_builds = pkg_set.get_many(to_build_ids)?;\n\n    // The ordering here affects some error messages coming out of cargo, so\n    // let's be test and CLI friendly by always printing in the same order if\n    // there's an error.\n    to_builds.sort_by_key(|p| p.package_id());\n\n    for pkg in to_builds.iter() {\n        pkg.manifest().print_teapot(gctx);\n\n        if build_config.intent.is_any_test()\n            && !ws.is_member(pkg)\n            && pkg.dependencies().iter().any(|dep| !dep.is_transitive())\n        {\n            anyhow::bail!(\n                \"package `{}` cannot be tested because it requires dev-dependencies \\\n                 and is not a member of the workspace\",\n                pkg.name()\n            );\n        }\n    }\n\n    let (extra_args, extra_args_name) = match (target_rustc_args, target_rustdoc_args) {\n        (Some(args), _) => (Some(args.clone()), \"rustc\"),\n        (_, Some(args)) => (Some(args.clone()), \"rustdoc\"),\n        _ => (None, \"\"),\n    };\n\n    if extra_args.is_some() && to_builds.len() != 1 {\n        panic!(\n            \"`{}` should not accept multiple `-p` flags\",\n            extra_args_name\n        );","sourceCodeStart":359,"sourceCodeEnd":395,"githubUrl":"https://github.com/rust-lang/cargo/blob/0e07a155371a6ce88ae53a2c00df940280c09a67/src/ops/cargo_compile/mod.rs#L359-L395","documentation":"Thrown when a build/test intent targets a package that is not a workspace member yet declares dev-dependencies. Cargo cannot build dev-dependencies for non-member packages because dev-deps are only resolved for workspace members, so testing them is impossible. The guard at src/ops/cargo_compile/mod.rs:373-382 checks is_any_test() intent, non-membership, and the presence of non-transitive (dev-only) dependencies before bailing.","triggerScenarios":"Running `cargo test -p <pkg>` (or cargo build with a test intent) where <pkg> is a path or git dependency pulled into the package set but not listed in the workspace's members. Concretely, the loop over to_builds hits a pkg with !ws.is_member(pkg) and a dev-dependency, while build_config.intent.is_any_test() is true.","commonSituations":"Trying to test a forked dependency via a path override (`-p my-dep`) without adding it to the workspace. Using [patch] / path dependencies and attempting to `cargo test -p` on the patched crate directly. Monorepo where a crate was moved out of the members list but tests are still run against it.","solutions":["Add the package to the workspace: list its path under [workspace] members in the root Cargo.toml so it becomes a workspace member.","If you cannot make it a member, remove or comment out its [dev-dependencies] (they are unusable for non-members anyway).","Run a non-test intent instead (e.g. `cargo build -p <pkg>`) if you only need a build, not tests.","Enter the dependency's own directory (where it has its own workspace) and run `cargo test` there, where it is the local member."],"exampleFix":"# before (root Cargo.toml)\n[workspace]\nmembers = [\"crates/main\"]\n# my-dep is a path dep, not a member; `cargo test -p my-dep` fails\n\n# after\n[workspace]\nmembers = [\"crates/main\", \"crates/my-dep\"]","handlingStrategy":"validation","validationCode":"// Before calling ops::compile with a test intent, verify the target pkg is a member.\nuse cargo::core::workspace::Workspace;\n\nfn can_test_package(ws: &Workspace, pkg: &cargo::core::Package) -> bool {\n    ws.is_member(pkg)\n        || !pkg.dependencies().iter().any(|d| !d.is_transitive())\n}\n\n// for spec selection: resolve -p names to members first\nlet bad: Vec<_> = specs.iter()\n    .filter(|n| !ws.members().any(|m| m.name().as_str() == n.as_str()))\n    .collect();\nassert!(bad.is_empty(), \"non-members selected for test: {:?}\", bad);","typeGuard":"// Narrow a Package selection to only workspace members that are safe to test.\nfn testable_members<'a>(ws: &'a Workspace<'a>) -> impl Iterator<Item = &'a cargo::core::Package> {\n    ws.members().filter(|p| p.dependencies().iter().all(|d| d.is_transitive()))\n}","tryCatchPattern":"// ops::compile returns CargoResult; surface the error to the user verbatim.\nmatch ops::compile(ws, &compile_opts) {\n    Ok(_) => {}\n    Err(e) if e.to_string().contains(\"cannot be tested\") => {\n        eprintln!(\"package is not a workspace member; add it to [workspace] members\");\n        return Err(e);\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Keep crates you intend to test as workspace members.","In CI, assert every -p name resolves to a member before running cargo test.","Avoid path/git overrides for crates you need to test in-place."],"tags":["cargo","workspace","dev-dependencies","testing","manifest"],"analyzedSha":"0e07a155371a6ce88ae53a2c00df940280c09a67","analyzedAt":"2026-08-06T01:46:58.334Z","schemaVersion":2}