rust-lang/rust-analyzer · error
unable to get FileId
Error message
unable to get FileId
What it means
CheckIfIndexed deferred task converts a file URI into an internal FileId and only then checks index status. The code already handles None gracefully via if-let, so the expect fires only when from_proto::file_id returns Err — i.e. the URI cannot be converted (unsupported scheme such as untitled:/, or URL parsing failure). Since the error case is otherwise handled, this expect is an over-strict assertion on an unreachable-in-practice branch.
Source
Thrown at crates/rust-analyzer/src/main_loop.rs:1091
Some(message),
Some(Progress::fraction(n_done, n_total)),
None,
)
}
}
}
}
}
fn handle_deferred_task(&mut self, task: DeferredTask) {
match task {
DeferredTask::CheckIfIndexed(uri) => {
let snap = self.snapshot();
self.task_pool.handle.spawn_with_sender(ThreadIntent::Worker, move |sender| {
let _p = tracing::info_span!("GlobalState::check_if_indexed").entered();
tracing::debug!(?uri, "handling uri");
let Some(id) = from_proto::file_id(&snap, &uri).expect("unable to get FileId")
else {
return;
};
if let Ok(crates) = &snap.analysis.crates_for(id) {
if crates.is_empty() {
if snap.config.discover_workspace_config().is_some() {
let path =
from_proto::abs_path(&uri).expect("Unable to get AbsPath");
let arg = DiscoverProjectParam::Path(path);
sender.send(Task::DiscoverLinkedProjects(arg)).unwrap();
}
} else {
tracing::debug!(?uri, "is indexed");
}
}
});
}
DeferredTask::CheckProcMacroSources(modified_rust_files) => {View on GitHub (pinned to e8f7e90aa3)
Solutions
- Avoid running rust-analyzer analysis over virtual/untitled URIs, or save the file to disk first.
- Upgrade rust-analyzer — this branch should map Err to the existing `return` path instead of panicking.
- Identify which extension/client produced the URI from logs (the `?uri` debug field) and disable the offending virtual-document provider for .rs files.
- As a workaround, disable workspace linking/deferred indexing on that URI by closing the virtual editor.
Example fix
// before
let Some(id) = from_proto::file_id(&snap, &uri).expect("unable to get FileId") else { return; };
// after: treat conversion error like the not-found case
let Ok(id) = from_proto::file_id(&snap, &uri) else { return; }; Defensive patterns
Strategy: fallback
Validate before calling
// server-side guard: skip non-file URIs before the deferred task
if uri.scheme().as_str() != "file" { return; } Type guard
fn is_file_uri(uri: &lsp_types::Url) -> bool {
uri.scheme() == "file"
} Try / catch
// if you cannot patch the server, avoid triggering it client-side
if (doc.uri.scheme !== 'file') { return; } // don't expect indexing for untitled/virtual docs Prevention
- Save untitled Rust files to disk before expecting analysis features.
- Exclude virtual document providers (notebooks, scratch pads) from rust-analyzer activation.
- Keep rust-analyzer updated; this expect is a known over-strict assertion.
- Check the logged `?uri` when diagnosing which producer sent the bad URI.
When it happens
Trigger: A textDocument URI with a non-file scheme (untitled:, vscode-notebook-cell:, remote authority prefixes) or a malformed URI reaching the CheckIfIndexed task after didOpen/didChange, causing from_proto::file_id to return Err instead of Ok(None).
Common situations: Editing untitled scratch files, remote/SSH or web (VS Code web) development where URIs carry non-standard schemes, extensions that synthesize virtual document URIs, and notebooks embedding Rust code.
Related errors
- Unable to get AbsPath
- received response for unknown request
- we never provide completions for excluded files
- we never provide code actions for excluded files
- No title could be found; this is a bug
AI-assisted analysis of rust-lang/rust-analyzer@e8f7e90aa3 (2026-09-03).
Data as JSON: /api/errors/8ac9b35de867a5dc.
Report an issue: GitHub.