astral-sh/ruff · error
Notebook document path does not point to a notebook document
Error message
Notebook document path does not point to a notebook document
What it means
On notebookDocument/didChange, the notebook key resolved to a document that is not a notebook (as_notebook_mut() returned None), so update_notebook_document bails (index.rs:76). The index stores text and notebook documents under distinct key namespaces; a mismatch means the client used the notebook API for a plain text document.
Source
Thrown at crates/ty_server/src/session/index.rs:76
#[expect(dead_code)]
fn notebook_document_keys(&self) -> impl Iterator<Item = &DocumentKey> + '_ {
self.documents
.iter()
.filter(|(_, doc)| doc.as_notebook().is_some())
.map(|(key, _)| key)
}
pub(super) fn update_notebook_document(
&mut self,
notebook_key: &DocumentKey,
cells: Option<lsp_types::NotebookDocumentCellChanges>,
metadata: Option<serde_json::Map<String, serde_json::Value>>,
new_version: DocumentVersion,
encoding: PositionEncoding,
) -> crate::Result<()> {
let document = self.document_mut(notebook_key)?;
let Some(notebook) = document.as_notebook_mut() else {
anyhow::bail!("Notebook document path does not point to a notebook document");
};
let (structure, data, text_content) = cells
.map(|cells| {
let lsp_types::NotebookDocumentCellChanges {
structure,
data,
text_content,
} = cells;
(structure, data, text_content)
})
.unwrap_or_default();
let (array, did_open, did_close) = structure
.map(|structure| {
let lsp_types::NotebookDocumentCellChangeStructure {
array,
did_open,View on GitHub (pinned to 672bb4edf0)
Solutions
- Always open via didOpenNotebookDocument before sending notebook didChange
- Match the exact notebookDocument.uri used in the didOpen
- After a desync, reopen the notebook file to re-register it as a notebook
Example fix
// before
notify('notebookDocument/didChange', { notebookDocument: { uri, version }, ... });
// after
notify('notebookDocument/didOpen', { notebookDocument: { uri, version, notebookType, cells } });
notify('notebookDocument/didChange', { notebookDocument: { uri, version }, change }); Defensive patterns
Strategy: type-guard
Validate before calling
// TS: only send notebook didChange for URIs opened as notebooks
const openNotebooks = new Set<string>();
client.onNotification('notebookDocument/didOpen', () => {}); // track via your own didOpen calls
function changeNotebook(uri: string, change: unknown) {
if (!openNotebooks.has(uri)) return; // never opened -> would hit the bail
notify('notebookDocument/didChange', { notebookDocument: { uri, version: next() }, change });
} Type guard
const isOpenNotebook = (uri: string): boolean => openNotebooks.has(uri);
Prevention
- Pair every notebookDocument/didChange with a prior didOpenNotebookDocument of the same URI
- On editor restart/replay, re-send notebook didOpen before didChange
- Don't send notebook notifications for plain .py files — the server stores those as text documents
When it happens
Trigger: Sending notebookDocument/didChange for a URI the server stored as a text document — e.g. never sending didOpenNotebookDocument first, or addressing a regular .py file with the notebook notification.
Common situations: Clients skipping notebook didOpen, restart races where the editor replays didChange for a notebook the server never saw, or a mismatched pair of client/server notebook-protocol versions.
Related errors
- Text document path does not point to a text document
- InvalidParams
- Failed to get the current working directory while creating a
- MethodNotFound
- InternalError
AI-assisted analysis of astral-sh/ruff@672bb4edf0 (2026-08-16).
Data as JSON: /api/errors/1863cb449d9d0590.
Report an issue: GitHub.