rust-lang/rust-analyzer · critical

Invariant violation: file emitted multiple times.

Error message

Invariant violation: file emitted multiple times.

What it means

The `scip` CLI command emits one SCIP document per source file. It tracks emitted files in a `file_ids_emitted` set and asserts each `file_id` is inserted exactly once; a duplicate means the index produced two documents for the same file, violating SCIP's one-document-per-file invariant, so `run` panics.

Source

Thrown at crates/rust-analyzer/src/cli/scip.rs:229

            }

            if occurrences.is_empty() {
                continue;
            }

            let position_encoding =
                scip_types::PositionEncoding::UTF8CodeUnitOffsetFromLineStart.into();
            documents.push(scip_types::Document {
                relative_path,
                language: "rust".to_owned(),
                occurrences,
                symbols,
                text: String::new(),
                position_encoding,
                special_fields: Default::default(),
            });
            if !file_ids_emitted.insert(file_id) {
                panic!("Invariant violation: file emitted multiple times.");
            }
        }

        // Collect all symbols referenced by the files but not defined within them.
        let mut external_symbols = Vec::new();
        for id in token_ids_referenced.difference(&token_ids_emitted) {
            let id = *id;
            let token = si.tokens.get(id).unwrap();

            let Some(definition) = token.definition else {
                continue;
            };

            let file_id = definition.file_id;
            let Some(relative_path) = get_relative_filepath(&vfs, &root, file_id) else { continue };
            let line_index = get_line_index(db, file_id);
            let text_range = definition.range;
            if file_ids_emitted.contains(&file_id) {

View on GitHub (pinned to e8f7e90aa3)

Solutions

  1. Update rust-analyzer / the scip CLI to the latest version, as duplicate emission usually indicates an index bug
  2. Report the workspace layout that reproduces the duplicate (minimize to the offending crate configuration)
  3. As a workaround, deduplicate documents by file id before serialization in a local patch

Example fix

// before
if !file_ids_emitted.insert(file_id) {
    panic!("Invariant violation: file emitted multiple times.");
}
// after (workaround)
if !file_ids_emitted.insert(file_id) {
    eprintln!("skipping duplicate document for {file_id:?}");
    continue;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-check duplicates when possible
let mut seen = std::collections::HashSet::new();
for doc in documents {
    assert!(seen.insert(doc.file_id));
}

Try / catch

std::panic::catch_unwind(|| scip::run(args))
    .err()
    .map(|_| eprintln!("scip generation produced duplicate file documents; report workspace layout"));

Prevention

When it happens

Trigger: Running `rust-analyzer scip` over a workspace where the same file (e.g. via overlapping crate roots, include-like duplication, or a token-mapping bug) yields more than one emission during the document loop.

Common situations: Workspaces with duplicated/aliased crate data; a rust-analyzer bug in file-id to document mapping; generated or macro-expanded files mapped back to the same file id twice.

Related errors


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