rust-lang/rust-analyzer · error

missing default crate root, specify a main.rs or lib.rs

Error message

missing default crate root, specify a main.rs or lib.rs

What it means

parse_with_proc_macros builds a CrateGraph from the fixture. If no crates were declared in the fixture, it falls back to a single default crate whose root file comes from default_crate_root; when that Option is None the expect panics. It means neither fixture-declared crates (with `-/-` crate root syntax) nor a default main.rs/lib.rs root were available.

Source

Thrown at crates/test-fixture/src/lib.rs:425

                crate_ws_data.clone(),
            );

            (
                move || {
                    DependencyBuilder::with_prelude(
                        CrateName::new("core").unwrap(),
                        core_crate,
                        true,
                        true,
                    )
                },
                core_crate,
            )
        });

        if crates.is_empty() {
            let crate_root = default_crate_root
                .expect("missing default crate root, specify a main.rs or lib.rs");
            let root = crate_graph.add_crate_root(
                crate_root,
                default_edition,
                Some(CrateName::new("ra_test_fixture").unwrap().into()),
                None,
                default_cfg.clone(),
                Some(default_cfg),
                default_env,
                CrateOrigin::Local { repo: None, name: None },
                Vec::new(),
                false,
                proc_macro_cwd.clone(),
                crate_ws_data.clone(),
            );
            if let Some((mini_core, _)) = mini_core {
                crate_graph.add_dep(root, mini_core()).unwrap();
            }
        } else {

View on GitHub (pinned to e8f7e90aa3)

Solutions

  1. Declare a crate root in the fixture using the `-/-` separator with lib.rs/main.rs, e.g. `"//- /lib.rs crate:main fn main() {}"`.
  2. Pass a default_crate_root (FileId pointing at your fixture's root file) when calling parse_with_proc_macros directly.
  3. Use TestDb::with_single_file-style helpers which supply a default root automatically.
  4. Check ChangeFixture::parse output: if your fixture text was consumed as a proc-macro/dependency directive, fix the directive syntax.

Example fix

// before
let db = TestDb::parse_with_proc_macros(fixture_text, /* no default root */ None);
// after
let db = TestDb::parse_with_proc_macros(
    "//- /lib.rs crate:main deps:foo
fn main() {}",
    Some(default_lib_file_id),
);
Defensive patterns

Strategy: validation

Validate before calling

fn assert_fixture_declares_root(fixture: &str) {
    let has_root = fixture.contains("-/-") || fixture.contains("lib.rs") || fixture.contains("main.rs");
    assert!(has_root, "fixture must declare a crate root or provide a default one");
}

Try / catch

// Avoid by construction; if calling parse_with_proc_macros directly:
match default_crate_root {
    Some(root) => parse_with_proc_macros(text, Some(root)),
    None => panic!("supply default_crate_root or declare `-/- /lib.rs` in the fixture"),
}

Prevention

When it happens

Trigger: Calling parse_with_proc_macros (public API) with an empty crate list and without supplying default_crate_root — e.g. a fixture with proc-macro/dep declarations but no `-/-` root directive, or a fixture that parses to zero crates.

Common situations: Programmatically constructing fixtures with proc macros but forgetting the `-/-` crate-root annotation; calling the public fixture API directly rather than through TestDb helpers that set a default root; typos in the crate-root marker so it isn't recognized.

Related errors


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