Where does the bug appear (feature/product)?
Cursor IDE
Describe the Bug
The EditNotebook tool (used by AI agents to edit Jupyter notebook cells) silently strips required fields from the notebook JSON when it re-serializes the .ipynb file. This happens even to cells and outputs that were not edited — the tool rewrites the entire file and loses data in the process.
Two categories of fields are stripped:
-
Cell
"id"fields (introduced in nbformat v4.5): Every cell in the notebook loses its"id". While older notebooks may not have these, stripping them from notebooks that do is data loss. -
Stream output
"name"fields (required by nbformat v4 spec): Everystream-type output loses its"name"field (which must be"stdout"or"stderr"). This makes the notebook invalid per the nbformat specification and breaks downstream tools such as Sphinx, myst-nb, and nbconvert that validate notebook structure.
Importance: High
This bug breaks the core workflow of agents editing Jupyter notebooks. Every single EditNotebook invocation silently corrupts the notebook file. Users who rely on agents for iterative notebook editing (a common workflow in data science / ML projects) will find their notebooks fail to render, fail CI checks, or produce broken documentation — with no warning from the tool itself.
Steps to Reproduce
-
Open any valid
.ipynbnotebook that has:- Cells with
"id"fields (standard since nbformat 4.5 / Jupyter Notebook 7+) - Code cells with
streamoutputs containing a"name"field (e.g. any cell that prints output)
- Cells with
-
Ask the AI agent to make a trivial text edit to a markdown cell using
EditNotebook(e.g. fix a typo). -
Inspect the saved
.ipynbfile:
import json
with open("your_notebook.ipynb") as f:
nb = json.load(f)
# Check cell ids
has_id = sum(1 for c in nb["cells"] if "id" in c)
print(f"Cells with 'id': {has_id} / {len(nb['cells'])}")
# Check stream output 'name' fields
for i, cell in enumerate(nb["cells"]):
for j, output in enumerate(cell.get("outputs", [])):
if output.get("output_type") == "stream" and "name" not in output:
print(f"Cell {i}, output {j}: stream output MISSING required 'name' field")
Expected Behavior
EditNotebookshould only modify the cell content that was actually edited.- All other fields in the notebook JSON — including cell
"id"fields, output"name"fields, and any other metadata — should be preserved exactly as they were. - The tool should never produce a notebook that violates the nbformat specification.
Actual Behavior
- All cell
"id"fields are stripped (not just the edited cell’s). - All stream output
"name"fields are stripped (not just outputs in the edited cell). - The tool reports success with no warning that fields were dropped.
- The resulting notebook is invalid per nbformat v4 and breaks Sphinx/myst-nb doc builds,
nbconvert, and other tools that validate notebook structure.
Operating System
Windows 10/11
MacOS
Version Information
- OS: macOS 26.2 (arm64)
- Cursor Version: 2.4.28
- Commit: f3f5cec40024283013878b50c4f9be4002e0b580
- Architecture: arm64
For AI issues: which model did you use?
Claude-4.6-opus-high
Additional Information
Evidence from git history
We observed this across multiple EditNotebook invocations on the same notebook:
| State | Cells with "id" |
Stream outputs with "name" |
|---|---|---|
| Before EditNotebook | 44 / 44 | 6 / 6 |
| After EditNotebook | 0 / 44 | 0 / 6 |
The fields are stripped from every cell and output in the notebook, not just the ones that were edited.
Does this stop you from using Cursor
No - Cursor works, but with this issue