{"record":{"id":"e8b4b46e54164716","repo":"astral-sh/ruff","slug":"text-document-path-does-not-point-to-a-text-docume","errorCode":null,"errorMessage":"Text document path does not point to a text document","messagePattern":"Text document path does not point to a text document","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/ty_server/src/session.rs","lineNumber":1825,"sourceCode":"\n    pub(crate) fn is_cell_or_notebook(&self) -> bool {\n        matches!(self, Self::Cell { .. } | Self::Notebook { .. })\n    }\n\n    pub(crate) fn update_text_document(\n        &mut self,\n        session: &mut Session,\n        content_changes: Vec<TextDocumentContentChangeEvent>,\n        new_version: DocumentVersion,\n    ) -> crate::Result<()> {\n        let position_encoding = session.position_encoding();\n        {\n            let mut index = session.index_mut();\n\n            let document_mut = index.document_mut(&self.key())?;\n\n            let Some(document) = document_mut.as_text_mut() else {\n                anyhow::bail!(\"Text document path does not point to a text document\");\n            };\n\n            if content_changes.is_empty() {\n                document.update_version(new_version);\n            } else {\n                document.apply_changes(content_changes, new_version, position_encoding);\n            }\n\n            self.set_version(document.version());\n        }\n\n        self.update_in_db(session);\n\n        Ok(())\n    }\n\n    pub(crate) fn update_notebook_document(\n        &mut self,","sourceCodeStart":1807,"sourceCodeEnd":1843,"githubUrl":"https://github.com/astral-sh/ruff/blob/672bb4edf04c84f8b0753346359daee4057158f2/crates/ty_server/src/session.rs#L1807-L1843","documentation":"On textDocument/didChange, the document key in the server's index resolved to a notebook document (or non-text entry), so as_text_mut() returned None and the handler bailed (session.rs:1825). The server routes by key: sending the plain text-document notification for something stored as a notebook triggers it.","triggerScenarios":"Sending textDocument/didChange for a notebook document or a URI stored under the notebook namespace — e.g. a client that only implements half of the notebook protocol, or cell URIs reused across didOpen/didOpenNotebookDocument flows.","commonSituations":"Editors or extensions that open notebook cells as plain text documents after the notebook was registered, partial notebook support in custom clients, or out-of-order open notifications during notebook load.","solutions":["Use the notebook protocol for notebooks: didOpenNotebookDocument/didChangeNotebookDocument plus cell notifications in the correct order","Ensure the same cell URI is not first opened via plain didOpen","Reopen the notebook in the editor to resynchronize document state"],"exampleFix":"// before: notebook doc sent through the text-document flow\nnotify('textDocument/didChange', { textDocument: { uri: cellUri, version }, ... });\n\n// after: go through the notebook flow\nnotify('notebookDocument/didChange', {\n  notebookDocument: { uri: notebookUri, version },\n  change: { cells: { structure, data, textContent } },\n});","handlingStrategy":"type-guard","validationCode":"// TS: route changes by whether the doc belongs to a notebook\nconst isNotebookDoc = (uri: vscode.Uri): boolean =>\n  !!vscode.workspace.notebookDocuments.some(nb =>\n    nb.uri.toString() === uri.toString() ||\n    nb.getCells().some(c => c.document.uri.toString() === uri.toString()));\n\nif (isNotebookDoc(doc.uri)) {\n  // use notebookDocument/didChange for the parent notebook\n} else {\n  client.notify('textDocument/didChange', params);\n}","typeGuard":"const isNotebookCell = (uri: string): boolean =>\n  vscode.workspace.notebookDocuments.some(nb =>\n    nb.getCells().some(c => c.document.uri.toString() === uri));","tryCatchPattern":null,"preventionTips":["Implement the notebook protocol as a unit: didOpenNotebookDocument before any cell/text change","Never open a notebook cell URI with plain textDocument/didOpen","After desync symptoms, reopen the notebook to rebuild the server's index"],"tags":["lsp","notebook","did-change","document-mismatch"],"backgroundTag":null,"analyzedSha":"672bb4edf04c84f8b0753346359daee4057158f2","analyzedAt":"2026-08-16T08:54:05.464Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}