rust-lang/rust-analyzer · error

Could not find file position in fixture. Did you forget to a

Error message

Could not find file position in fixture. Did you forget to add an `$0`?

What it means

This panic comes from the test-fixture helper that parses a fixture string and extracts the cursor position. rust-analyzer test fixtures mark positions with `$0`; if the fixture text contains no `$0` marker, file_position is None and the expect panics. It means the test author forgot to mark where the cursor/selection should be.

Source

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

    #[track_caller]
    fn with_range(#[rust_analyzer::rust_fixture] ra_fixture: &str) -> (Self, FileRange) {
        let (db, file_id, range_or_offset) = Self::with_range_or_offset(ra_fixture);
        let range = range_or_offset.expect_range();
        (db, FileRange { file_id, range })
    }

    /// See the trait documentation for more information on fixtures.
    #[track_caller]
    fn with_range_or_offset(
        #[rust_analyzer::rust_fixture] ra_fixture: &str,
    ) -> (Self, EditionedFileId, RangeOrOffset) {
        let mut db = Self::default();
        let fixture = ChangeFixture::parse(ra_fixture);
        fixture.change.apply(&mut db);

        let (file_id, range_or_offset) = fixture
            .file_position
            .expect("Could not find file position in fixture. Did you forget to add an `$0`?");
        let file_id = EditionedFileId::from_span_file_id(&db, file_id);
        (db, file_id, range_or_offset)
    }

    fn test_crate(&self) -> Crate {
        all_crates(self).iter().copied().find(|&krate| !krate.data(self).origin.is_lang()).unwrap()
    }
}

impl<DB: SourceDatabase + Default + 'static> WithFixture for DB {}

pub struct ChangeFixture {
    pub file_position: Option<(span::EditionedFileId, RangeOrOffset)>,
    pub file_lines: Vec<usize>,
    pub files: Vec<span::EditionedFileId>,
    pub change: ChangeWithProcMacros,
    pub sysroot_files: Vec<FileId>,
}

View on GitHub (pinned to e8f7e90aa3)

Solutions

  1. Add `$0` inside the fixture text at the position of interest, e.g. `fn f() { foo$0(); }`.
  2. If using comment-based markers (`//^`), keep `$0` only if the API needs a cursor too; otherwise use the marker-based helper instead.
  3. Ensure `$0` appears exactly once if the helper expects a single file position.
  4. Check the fixture annotation syntax in docs/book/src/contributing/testing.md if unsure which marker your helper requires.

Example fix

// before
let (db, file_id, range) = TestDb::with_range_or_offset(r#"fn main() { foo(); }"#);
// after
let (db, file_id, range) = TestDb::with_range_or_offset(r#"fn main() { foo$0(); }"#);
Defensive patterns

Strategy: validation

Validate before calling

fn assert_fixture_has_cursor(fixture: &str) {
    assert!(fixture.contains("$0"), "fixture must contain $0 cursor marker");
}

Try / catch

// Called from #[should_panic] tests only; otherwise validate before calling:
assert!(ra_fixture.contains("$0"));
let (db, file_id, pos) = TestDb::with_range_or_offset(ra_fixture);

Prevention

When it happens

Trigger: Calling TestDb::with_range_or_offset (or helpers like with_single_file_with_position that go through it) with a ra_fixture string lacking `$0`, or where `$0` was consumed by another marker such as `//^` annotations without an actual `$0`.

Common situations: Writing a new expect/infer test and forgetting the cursor marker; copying a fixture that used `//^^^` comment annotations only; `$0` accidentally removed during fixture cleanup (testing conventions require minimal fixtures).

Related errors


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