astral-sh/ruff · error

InternalError

InternalError

Error message

Notebook document expected from notebook source kind

What it means

An InternalError from the ruff language server's fix pipeline: the document being fixed was classified as an ipynb notebook (source kind and transformed content both parsed as notebooks), but the session's stored query document could not be retrieved as a notebook. This is a broken internal invariant between the source-kind detection and the session document index, not a user configuration issue.

Solutions

  1. Restart the ruff language server / reload the editor window to rebuild the document index
  2. Update the ruff VS Code extension (and bundled server) — state-desync bugs in the notebook fix path get fixed over time
  3. If reproducible, capture the editor logs and file an issue at https://github.com/astral-sh/ruff/issues with the notebook and steps
Defensive patterns

Strategy: fallback

Prevention

When it happens

Trigger: Applying a code action / auto-fix on a .ipynb notebook open in the editor when the server's document index holds a stale or mismatched entry for that URI; typically after notebook cells were opened/closed rapidly or the server state desynchronized.

Common situations: Editor extension races during notebook editing; server restarted mid-session while notebook documents remained open; version skew between editor extension and ruff server.

Related errors


AI-assisted analysis of astral-sh/ruff@d1087a4b9e (2026-08-20). Data as JSON: /api/errors/3af3b6e3dd35bf23. Report an issue: GitHub.

Appendix: source

Thrown at crates/ruff_server/src/fix.rs:107

    }

    // fast path: if `transformed` is still borrowed, no changes were made and we can return early
    if let Cow::Borrowed(_) = transformed {
        return Ok(Fixes::default());
    }

    if let (Some(source_notebook), Some(modified_notebook)) =
        (source_kind.as_ipy_notebook(), transformed.as_ipy_notebook())
    {
        fn cell_source(cell: &ruff_notebook::Cell) -> String {
            match cell.source() {
                SourceValue::String(string) => string.clone(),
                SourceValue::StringArray(array) => array.join(""),
            }
        }

        let Some(notebook) = query.as_notebook() else {
            anyhow::bail!("Notebook document expected from notebook source kind");
        };
        let mut fixes = Fixes::default();
        for ((source, modified), uri) in source_notebook
            .cells()
            .iter()
            .map(cell_source)
            .zip(modified_notebook.cells().iter().map(cell_source))
            .zip(notebook.uris())
        {
            let source_index = LineIndex::from_source_text(&source);
            let modified_index = LineIndex::from_source_text(&modified);

            let Replacement {
                source_range,
                modified_range,
            } = Replacement::between(
                &source,
                source_index.line_starts(),

View on GitHub (pinned to d1087a4b9e)