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

ty_server maintains one document per path in its session, which can be either a text document or a notebook document. update_notebook_document expects the document at notebook_key.uri to be a notebook; when it is stored as a plain text document (or vice versa), the downcast to a notebook fails and the server bails with this message.

Solutions

  1. Ensure the client sends notebookDocument/didOpen (not textDocument/didOpen) for notebook URIs before sending notebook change events
  2. Check the server's did_open/did_close handlers so a document is closed and re-registered as a notebook when its kind changes
  3. Log/inspect the session's document kind at the given path before calling update_notebook_document
  4. Return a typed error instead of anyhow::bail! so clients can react to the kind mismatch

Example fix

// before
let Some(notebook) = document.as_notebook_mut() else {
    anyhow::bail!("Notebook document path does not point to a notebook document");
};
// after
let Some(notebook) = document.as_notebook_mut() else {
    return Err(crate::Error::new(
        format!("document at {} is not a notebook (kind: {:?})", notebook_key.uri, document.kind()),
    ));
};
Defensive patterns

Strategy: type-guard

Validate before calling

fn is_notebook(session: &Session, uri: &Url) -> bool {
    session.document(uri).map(|d| d.as_notebook().is_some()).unwrap_or(false)
}
// call update_notebook_document only if is_notebook(...)

Type guard

fn as_notebook(document: &Document) -> Option<&Notebook> {
    document.as_notebook()
}

Try / catch

if let Err(err) = session.update_notebook_document(...) {
    if err.to_string().contains("does not point to a notebook document") {
        // fall back to plain-text document update path
    }
}

Prevention

When it happens

Trigger: Calling session.update_notebook_document (e.g. from a notebookDocument/didChange LSP notification) for a URI whose entry in the session documents map was opened as a regular text document, or whose kind changed between didOpen and didChange.

Common situations: An LSP client opens the same .ipynb file both as a text document and as a notebook document, a client sends notebook change notifications for a path it never opened as a notebook, or editor tooling (diff views, virtual copies) creates a plain-text document at a notebook path.

Related errors


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

Appendix: 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 26f38c119c)