## TL;DR
Interrupting the kernel while it writes the notebook can truncate the file mid-object, so the next open fails with a JSON decode error. First try the automatic checkpoint Jupyter keeps next to the notebook; if that is stale or missing, find the syntax break with a JSON parser (it reports the line and column) and repair the truncation by closing the open structures. Never hand-edit blindly: validate after every repair attempt.

```text
agent interrupted the kernel mid-write: notebook JSON corrupted
```

## Use this when
- The notebook will not open and the error mentions invalid JSON or unexpected end of data.
- An agent interrupted a long-running cell and the notebook file changed size suspiciously.
- The file opens in a text editor but Jupyter refuses it.

## Not for this skill when
- The notebook opens but nbformat validation fails on schema. That is a schema problem, a different fix.
- The file contains git merge-conflict markers. That is a merge problem, not corruption.

## Steps
1. Back up the corrupted file before touching it. Expected: a byte-identical copy exists outside the working tree.
2. Check for an automatic checkpoint: look in the `.ipynb_checkpoints` directory next to the notebook. Expected: either a recent checkpoint to restore or confirmation that none is usable.
3. Locate the break: run `python -m json.tool notebook.ipynb` and read the error's line and column. Expected: the exact position where the JSON becomes invalid.
4. If the file is truncated (ends mid-structure), repair by removing the partial tail and closing the open objects, keeping every complete cell. Expected: `python -m json.tool` now parses the file.
5. Validate as a notebook: `python -c "import nbformat; nbformat.read('notebook.ipynb', as_version=4)"`. Expected: no validation error.
6. Open in Jupyter and run the cells that were executing when the interrupt happened, since their outputs are lost. Expected: the notebook is whole and re-executed where needed.
7. Prevent recurrence: agents should interrupt the kernel and THEN wait for the save to complete (or trigger an explicit save) before killing anything. Expected: the interrupt-then-save ordering is in the agent's runbook.

## Tool compatibility
nbformat 5.x; notebook 6.x/7.x and JupyterLab 3.x/4.x checkpointing; Python 3.9+.

## Variant phrasings
### notebook won't open invalid json after interrupt
The symptom phrasing. Check the checkpoint, then locate the break with json.tool.

### ipynb corrupted kernel interrupted
The cause phrasing. Truncation mid-write; repair the tail or restore the checkpoint.

### json decode error opening notebook
The parser phrasing. The reported line and column point at the damage.

## Why it happens
Notebook saving is not atomic in the classic flow: the kernel serializes the whole document and streams it to disk, and an interrupt that lands mid-write leaves a file that is valid JSON up to some byte offset and garbage or nothing after it. Jupyter keeps a checkpoint copy from the last successful save, which is why the first recovery step is always the checkpoint, not surgery. When the checkpoint is too old, the JSON parser's error position is the most precise diagnostic available: it tells you exactly where validity ends, and everything before that point is intact. Repair is then a matter of truncating the damaged tail cleanly, not of reconstructing content.

## Edge cases / pitfalls
- Repairing by deleting cells you cannot verify loses work silently. Prefer the checkpoint whenever it is recent enough.
- A file that parses as JSON can still fail nbformat validation (missing required keys). Always run the nbformat read check after the JSON check.
- Agents that kill -9 the kernel process bypass graceful shutdown entirely. Prefer interrupt signals and wait for the save.
- Do not commit a repaired notebook without re-running it. Repaired cells may carry outputs from a different execution state.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_jfWuyBg2x2soeut6gyxDlQ
