rust-lang/rust-analyzer · error

no projects

Error message

no projects

What it means

discover_single expects exactly one project manifest under the given path. It calls discover(), and if the returned candidate list is empty it bails with "no projects". It means the given root contains no Cargo.toml, rust-project.json, or script.rs that discovery can find.

Source

Thrown at crates/project-model/src/lib.rs:121

        }
        if path.file_name().unwrap_or_default() == ".rust-project.json" {
            return Ok(ProjectManifest::ProjectJson(path));
        }
        if path.file_name().unwrap_or_default() == "Cargo.toml" {
            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());

View on GitHub (pinned to e8f7e90aa3)

Solutions

  1. cd into (or point at) the directory containing Cargo.toml or rust-project.json.
  2. Create a Cargo.toml (`cargo init`) if the directory should be a Rust project.
  3. Use ProjectManifest::discover() instead if you want to handle zero/many projects explicitly.
  4. Provide a rust-project.json for non-Cargo builds.

Example fix

// before
let manifest = ProjectManifest::discover_single(&empty_dir)?; // bails
// after
let manifest = ProjectManifest::discover_single(&workspace_dir.join("crates/foo"))?;
Defensive patterns

Strategy: validation

Validate before calling

fn has_manifest(dir: &Path) -> bool {
    dir.join("Cargo.toml").is_file()
        || dir.join("rust-project.json").is_file()
        || dir.ancestors().any(|a| a.join("Cargo.toml").is_file())
}
// if !has_manifest(&root) { create one or fix the path first }

Try / catch

match ProjectManifest::discover_single(&path) {
    Ok(m) => m,
    Err(e) if e.to_string() == "no projects" => {
        let candidates = ProjectManifest::discover(&path)?;
        if candidates.is_empty() { /* init a project or abort */ }
        unreachable!()
    }
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: Calling `ProjectManifest::discover_single(&abs_path)` on a directory with no Cargo.toml/rust-project.json anywhere it searches, so discover() returns an empty Vec.

Common situations: Running rust-analyzer in an empty or non-Rust directory; wrong working directory; project files ignored by discovery (e.g. manifest inside a subdir while pointing at the parent); a checkout missing manifests due to sparse clone.

Related errors


AI-assisted analysis of rust-lang/rust-analyzer@e8f7e90aa3 (2026-09-03). Data as JSON: /api/errors/cf62f65843bd5af9. Report an issue: GitHub.