{"record":{"id":"43c91e9330a63679","repo":"astral-sh/ruff","slug":"failed-to-read-notebook-file","errorCode":null,"errorMessage":"Failed to read notebook file `{}`: {:?}","messagePattern":"Failed to read notebook file `(.+?)`: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/ruff_notebook/src/notebook.rs","lineNumber":25,"sourceCode":"use std::io;\nuse std::io::{BufReader, Cursor, Read, Seek, SeekFrom, Write};\nuse std::path::Path;\nuse std::sync::OnceLock;\nuse thiserror::Error;\n\nuse ruff_diagnostics::{SourceMap, SourceMarker};\nuse ruff_source_file::{OneIndexed, UniversalNewlineIterator};\nuse ruff_text_size::{TextRange, TextSize};\n\nuse crate::cell::CellOffsets;\nuse crate::index::NotebookIndex;\nuse crate::schema::{Cell, RawNotebook, SortAlphabetically, SourceValue};\nuse crate::{CellMetadata, CellStart, RawNotebookMetadata, SYNTHETIC_CELL_SEPARATOR, schema};\n\n/// Run round-trip source code generation on a given Jupyter notebook file path.\npub fn round_trip(path: &Path) -> anyhow::Result<String> {\n    let mut notebook = Notebook::from_path(path).map_err(|err| {\n        anyhow::anyhow!(\n            \"Failed to read notebook file `{}`: {:?}\",\n            path.display(),\n            err\n        )\n    })?;\n    let code = notebook.source_code().to_string();\n    let needs_rebuild = notebook.update_cell_content(&code);\n    debug_assert!(\n        !needs_rebuild,\n        \"round-tripping unchanged source cannot remove a synthetic cell separator\"\n    );\n    let mut writer = Vec::new();\n    notebook.write(&mut writer)?;\n    Ok(String::from_utf8(writer)?)\n}\n\n/// An error that can occur while deserializing a Jupyter Notebook.\n#[derive(Error, Debug)]","sourceCodeStart":7,"sourceCodeEnd":43,"githubUrl":"https://github.com/astral-sh/ruff/blob/26f38c119cac42e4d320ba08f09224fdec74af2c/crates/ruff_notebook/src/notebook.rs#L7-L43","documentation":"`ruff_notebook::round_trip` runs Jupyter notebook round-trip source generation on a file path. If the notebook cannot be loaded from disk (missing file, parse error, schema failure), the underlying Notebook::from_path error is wrapped with the path and error detail into this anyhow error.","triggerScenarios":"Calling `ruff_notebook::round_trip(path)` where `path` does not exist, is not readable, or contains a malformed/invalid `.ipynb` JSON document.","commonSituations":"Typo'd or stale notebook path passed to `ruff check --fix` on notebooks; notebooks produced by tools emitting non-conforming JSON; files deleted or moved between discovery and processing; permission problems in CI containers.","solutions":["Verify the path exists and is readable (`ls -l`, check permissions)","Validate the notebook JSON (e.g. `jq . notebook.ipynb` or jupyter's nbformat validate) and fix or regenerate the file","Re-run after the notebook is saved/closed to rule out a concurrent-writer partial file","If the file is intentionally not a notebook, remove it from the lint/format target list"],"exampleFix":"// before\nlet code = round_trip(Path::new(\"outdated_notebook.ipynb\"))?;\n// after\nlet path = Path::new(\"analysis.ipynb\");\nassert!(path.exists(), \"notebook missing: {}\", path.display());\nlet code = round_trip(path)?;","handlingStrategy":"try-catch","validationCode":"// Rust-side pre-checks before round_trip\nuse std::path::Path;\n\nfn notebook_readable(path: &Path) -> bool {\n    path.is_file()\n        && std::fs::File::open(path)\n            .map(|mut f| {\n                use std::io::Read;\n                let mut buf = String::new();\n                f.read_to_string(&mut buf).is_ok()\n                    && serde_json::from_str::<serde_json::Value>(&buf).is_ok()\n            })\n            .unwrap_or(false)\n}","typeGuard":null,"tryCatchPattern":"// Rust\nmatch ruff_notebook::round_trip(path) {\n    Ok(code) => process(code),\n    Err(e) if e.to_string().contains(\"Failed to read notebook file\") => {\n        eprintln!(\"skipping notebook {path:?}: {e:#}\");\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Check path existence and permissions before invoking round_trip","Validate .ipynb files with nbformat/jq in CI before linting them","Exclude non-notebook files from notebook-aware lint/format globs","Regenerate notebooks that fail JSON validation instead of editing them in place"],"tags":["rust","jupyter","notebook","file-io"],"backgroundTag":"notebook-file-unreadable","analyzedSha":"26f38c119cac42e4d320ba08f09224fdec74af2c","analyzedAt":"2026-09-05T10:32:37.492Z","contentChangedAt":"2026-09-05T10:32:37.492Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}