astral-sh/ruff · error

Text document URI does not point to a text document

Error message

Text document URI does not point to a text document

What it means

`update_text_document` applies `textDocument/didChange` content edits to an indexed document. If the controller stored under the given document key is not a text document (e.g. it is a notebook), the update cannot proceed and the server bails. This guards against applying plain-text incremental edits to non-text document types.

Solutions

  1. Send `notebookDocument/didChange` for notebook documents instead of `textDocument/didChange`
  2. Verify the URI in didChange matches the URI that was opened via `textDocument/didOpen`
  3. Close and reopen the document if its type changed server-side (restart the Ruff server to reset state)
Defensive patterns

Strategy: validation

Validate before calling

// client-side check before sending didChange
if (openedAsNotebook.has(uri)) {
  sendNotebookDidChange(doc); // not textDocument/didChange
} else {
  sendTextDocumentDidChange(doc);
}

Type guard

fn is_text_document(controller: &DocumentController) -> bool { matches!(controller.as_text(), Some(_)) }

Try / catch

if let Err(e) = session.update_text_document(&key, changes, version, enc) { if e.to_string().contains("not point to a text document") { /* resend via notebook path */ } }

Prevention

When it happens

Trigger: Calling `session.update_text_document(key, content_changes, new_version, encoding)` where `document_controller_for_key` returns a `DocumentController` whose inner document is a notebook rather than text; `as_text_mut()` returns None.

Common situations: A client sends `textDocument/didChange` for a URI that Ruff indexed as part of a notebook (`notebookDocument/didOpen`); mixed-language editors sending text updates for cell documents.

Related errors


AI-assisted analysis of astral-sh/ruff@26f38c119c (2026-09-05). Data as JSON: /api/errors/279ef325b36ced5d. Report an issue: GitHub.

Appendix: source

Thrown at crates/ruff_server/src/session/index.rs:114

    }

    pub(super) fn notebook_document_uris(&self) -> impl Iterator<Item = &Uri> + '_ {
        self.documents
            .iter()
            .filter(|(_, doc)| doc.as_notebook().is_some())
            .map(|(uri, _)| uri)
    }

    pub(super) fn update_text_document(
        &mut self,
        key: &DocumentKey,
        content_changes: Vec<lsp_types::TextDocumentContentChangeEvent>,
        new_version: DocumentVersion,
        encoding: PositionEncoding,
    ) -> crate::Result<()> {
        let controller = self.document_controller_for_key(key)?;
        let Some(document) = controller.as_text_mut() else {
            anyhow::bail!("Text document URI does not point to a text document");
        };

        if content_changes.is_empty() {
            document.update_version(new_version);
            return Ok(());
        }

        document.apply_changes(content_changes, new_version, encoding);

        Ok(())
    }

    pub(super) fn key_from_uri(&self, uri: Uri) -> DocumentKey {
        if self.notebook_cells.contains_key(&uri) {
            DocumentKey::NotebookCell(uri)
        } else if self
            .documents
            .get(&uri)

View on GitHub (pinned to 26f38c119c)