rust-lang/cargo · error · anyhow::Error
package `{}` cannot be tested because it requires dev-depend
Error message
package `{}` cannot be tested because it requires dev-dependencies and is not a member of the workspace What it means
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.
Source
Thrown at src/ops/cargo_compile/mod.rs:377
let to_build_ids = resolve.specs_to_ids(&specs)?;
// Now get the `Package` for each `PackageId`. This may trigger a download
// if the user specified `-p` for a dependency that is not downloaded.
// Dependencies will be downloaded during build_unit_dependencies.
let mut to_builds = pkg_set.get_many(to_build_ids)?;
// The ordering here affects some error messages coming out of cargo, so
// let's be test and CLI friendly by always printing in the same order if
// there's an error.
to_builds.sort_by_key(|p| p.package_id());
for pkg in to_builds.iter() {
pkg.manifest().print_teapot(gctx);
if build_config.intent.is_any_test()
&& !ws.is_member(pkg)
&& pkg.dependencies().iter().any(|dep| !dep.is_transitive())
{
anyhow::bail!(
"package `{}` cannot be tested because it requires dev-dependencies \
and is not a member of the workspace",
pkg.name()
);
}
}
let (extra_args, extra_args_name) = match (target_rustc_args, target_rustdoc_args) {
(Some(args), _) => (Some(args.clone()), "rustc"),
(_, Some(args)) => (Some(args.clone()), "rustdoc"),
_ => (None, ""),
};
if extra_args.is_some() && to_builds.len() != 1 {
panic!(
"`{}` should not accept multiple `-p` flags",
extra_args_name
);View on GitHub (pinned to 0e07a15537)
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.
Example fix
# before (root Cargo.toml) [workspace] members = ["crates/main"] # my-dep is a path dep, not a member; `cargo test -p my-dep` fails # after [workspace] members = ["crates/main", "crates/my-dep"]
Defensive patterns
Strategy: validation
Validate before calling
// Before calling ops::compile with a test intent, verify the target pkg is a member.
use cargo::core::workspace::Workspace;
fn can_test_package(ws: &Workspace, pkg: &cargo::core::Package) -> bool {
ws.is_member(pkg)
|| !pkg.dependencies().iter().any(|d| !d.is_transitive())
}
// for spec selection: resolve -p names to members first
let bad: Vec<_> = specs.iter()
.filter(|n| !ws.members().any(|m| m.name().as_str() == n.as_str()))
.collect();
assert!(bad.is_empty(), "non-members selected for test: {:?}", bad); Type guard
// Narrow a Package selection to only workspace members that are safe to test.
fn testable_members<'a>(ws: &'a Workspace<'a>) -> impl Iterator<Item = &'a cargo::core::Package> {
ws.members().filter(|p| p.dependencies().iter().all(|d| d.is_transitive()))
} Try / catch
// ops::compile returns CargoResult; surface the error to the user verbatim.
match ops::compile(ws, &compile_opts) {
Ok(_) => {}
Err(e) if e.to_string().contains("cannot be tested") => {
eprintln!("package is not a workspace member; add it to [workspace] members");
return Err(e);
}
Err(e) => return Err(e),
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- {}package(s) `{}` not found in workspace `{}`
- no library targets found in packages: {}
- dependency `{}` in package `{}` requires a `{}` artifact to
- could not compile due to {error_count} previous target resol
- crate types can only be specified for libraries and example
AI-assisted analysis of rust-lang/cargo@0e07a15537 (2026-08-06).
Data as JSON: /data/errors/4b622d7284ce129b.json.
Report an issue: GitHub.