rust-lang/rust-analyzer · error
more than one project
Error message
more than one project
What it means
discover_single requires that discovery find exactly one project. After popping one candidate, any remaining candidates cause this bail, because the API is meant for an unambiguous single-project root (e.g. a rust-project.json describing one workspace).
Source
Thrown at crates/project-model/src/lib.rs:126
return Ok(ProjectManifest::CargoToml(path));
}
if path.extension().unwrap_or_default() == "rs" {
return Ok(ProjectManifest::CargoScript(path));
}
bail!(
"project root must point to a Cargo.toml, rust-project.json or <script>.rs file: {path}"
);
}
pub fn discover_single(path: &AbsPath) -> anyhow::Result<ProjectManifest> {
let mut candidates = ProjectManifest::discover(path)?;
let res = match candidates.pop() {
None => bail!("no projects"),
Some(it) => it,
};
if !candidates.is_empty() {
bail!("more than one project");
}
Ok(res)
}
pub fn discover(path: &AbsPath) -> io::Result<Vec<ProjectManifest>> {
if let Some(project_json) = find_in_parent_dirs(path, "rust-project.json") {
return Ok(vec![ProjectManifest::ProjectJson(project_json)]);
}
if let Some(project_json) = find_in_parent_dirs(path, ".rust-project.json") {
return Ok(vec![ProjectManifest::ProjectJson(project_json)]);
}
return find_cargo_toml(path)
.map(|paths| paths.into_iter().map(ProjectManifest::CargoToml).collect());
fn find_cargo_toml(path: &AbsPath) -> io::Result<Vec<ManifestPath>> {
match find_in_parent_dirs(path, "Cargo.toml") {
Some(it) => Ok(vec![it]),
None => Ok(find_cargo_toml_in_child_dir(read_dir(path)?)),View on GitHub (pinned to e8f7e90aa3)
Solutions
- Delete or move the extra manifest (e.g. remove a stale rust-project.json next to Cargo.toml).
- Point discover_single at the specific crate's Cargo.toml directory.
- Switch to ProjectManifest::discover() and pick the manifest you want programmatically.
Example fix
// before
let manifest = ProjectManifest::discover_single(&monorepo_root)?; // ambiguous
// after
let manifest = ProjectManifest::discover_single(&monorepo_root.join("crates/mylib"))?; Defensive patterns
Strategy: validation
Validate before calling
// count candidates before requesting a single project
let candidates = ProjectManifest::discover(&path)?;
if candidates.len() != 1 {
// pick explicitly: e.g. prefer rust-project.json, or error out with choices
} Try / catch
match ProjectManifest::discover_single(&path) {
Ok(m) => m,
Err(e) if e.to_string() == "more than one project" => {
let mut c = ProjectManifest::discover(&path)?;
c.retain(|m| matches!(m, ProjectManifest::CargoToml(_)));
c.pop().ok_or_else(|| anyhow!("no usable manifest"))?
}
Err(e) => return Err(e.into()),
} Prevention
- Remove stale rust-project.json files when a project moved to Cargo.
- Point discover_single at a specific crate directory, not a monorepo root.
- Use discover() with explicit selection logic in multi-project workspaces.
When it happens
Trigger: Calling `ProjectManifest::discover_single(&abs_path)` where discovery finds multiple manifests — e.g. a directory containing both a rust-project.json and Cargo.toml files, or several candidate manifests in parent/nested dirs.
Common situations: Pointing discover_single at a workspace root that also has a rust-project.json and Cargo.toml; monorepo with multiple crate manifests where the caller expected one; leftover rust-project.json from a prior non-Cargo setup.
Related errors
- no projects
- inconsistent text range
- project root must point to a Cargo.toml, rust-project.json o
- No file available to rename
- Invalid name `{}`: cannot rename to a keyword
AI-assisted analysis of rust-lang/rust-analyzer@e8f7e90aa3 (2026-09-03).
Data as JSON: /api/errors/8ccabfa65a620542.
Report an issue: GitHub.