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
- Update rust-analyzer / the scip CLI to the latest version, as duplicate emission usually indicates an index bug
- Report the workspace layout that reproduces the duplicate (minimize to the offending crate configuration)
- 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
- Update to the latest rust-analyzer where scip duplicate-emission bugs may be fixed
- Minimize and report workspaces that trigger duplicate file ids (aliased crate roots, generated files)
- Deduplicate documents by file id before serializing SCIP output
- Run the scip export on a clean, non-overlapping crate graph when possible
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
- We explicitly do not provide canonicalization API, as that i
- bad kind {other}
- bad spacing {other}
- bad tag: {other}
- profiler already started
AI-assisted analysis of rust-lang/rust-analyzer@e8f7e90aa3 (2026-09-03).
Data as JSON: /api/errors/4b44d008e2546290.
Report an issue: GitHub.