astral-sh/ruff · error
tried to close document that didn't exist at
Error message
tried to close document that didn't exist at {uri} What it means
In `close_document`, after resolving the key to a URI, the server removes the document entry from `self.documents`. If the URI is known but no document is registered under it, the index is internally inconsistent and the server bails. This is a stricter, lower-level check than error 84.
Solutions
- Restart the Ruff server to rebuild a consistent document index
- Avoid sending didClose for the same document more than once
- If developing against ruff_server, check that document insertion and mapping updates are atomic in open paths
Defensive patterns
Strategy: try-catch
Try / catch
if let Err(e) = session.close_document(&key, enc) { if e.to_string().contains("didn't exist") { log.warn("inconsistent document index; restarting server"); restart_server(); } } Prevention
- Avoid double-closing documents; track open state client-side
- Restart the Ruff server if you suspect desynchronized session state
- When embedding ruff_server, keep key-to-URI mappings and document entries updated atomically
When it happens
Trigger: Calling `session.close_document(key, encoding)` where `uri_for_key(key)` succeeds but `self.documents.remove(&uri)` returns None — the key-to-URI mapping exists without a corresponding registered document.
Common situations: Race or bookkeeping bug where mappings and documents are inserted/removed out of sync; double-close where only the mapping persisted; partial initialization failure.
Related errors
- Document controller not available at
- Notebook document URI does not point to a notebook document
- Text document URI does not point to a text document
- Tried to close unavailable document
- Tried to open unavailable document
AI-assisted analysis of astral-sh/ruff@26f38c119c (2026-09-05).
Data as JSON: /api/errors/7b1a8974b74de6d2.
Report an issue: GitHub.
Appendix: source
Thrown at crates/ruff_server/src/session/index.rs:331
pub(super) fn close_document(&mut self, key: &DocumentKey) -> crate::Result<()> {
// Notebook cells URIs are removed from the index here, instead of during
// `update_notebook_document`. This is because a notebook cell, as a text document,
// is requested to be `closed` by VS Code after the notebook gets updated.
// This is not documented in the LSP specification explicitly, and this assumption
// may need revisiting in the future as we support more editors with notebook support.
if let DocumentKey::NotebookCell(uri) = key {
if self.notebook_cells.remove(uri).is_none() {
tracing::warn!("Tried to remove a notebook cell that does not exist: {uri}",);
}
return Ok(());
}
let Some(uri) = self.uri_for_key(key).cloned() else {
anyhow::bail!("Tried to close unavailable document `{key}`");
};
let Some(_) = self.documents.remove(&uri) else {
anyhow::bail!("tried to close document that didn't exist at {uri}")
};
Ok(())
}
pub(super) fn client_settings(&self, key: &DocumentKey) -> Option<Arc<ClientSettings>> {
let uri = self.uri_for_key(key)?;
let WorkspaceSettings {
client_settings, ..
} = self.settings_for_uri(uri)?;
Some(client_settings.clone())
}
fn document_controller_for_key(
&mut self,
key: &DocumentKey,
) -> crate::Result<&mut DocumentController> {
let Some(uri) = self.uri_for_key(key).cloned() else {
anyhow::bail!("Tried to open unavailable document `{key}`");View on GitHub (pinned to 26f38c119c)