## TL;DR
Hand-editing the notebook JSON introduced something the nbformat schema rejects: a missing `cell_type`, a wrong `metadata` shape, or malformed JSON around your edit. Do not keep guessing; run `python -c "import nbformat; nbformat.read('nb.ipynb', as_version=4)"` and read the validation message, which names the offending location. Fix that spot, re-validate, and only then reopen in Jupyter.

```text
NotebookValidationError: nbformat validation failed after manual edit
```

## Use this when
- A notebook that you edited as raw JSON now fails validation on open or read.
- The error message cites a schema path like `cells[12].source`.
- A script that rewrites notebooks produces files Jupyter rejects.

## Not for this skill when
- The notebook opens but cells fail. That is code, not structure.
- The file will not parse as JSON at all. Fix the JSON syntax first, then the schema.

## Steps
1. Back up the file before touching it further: `cp nb.ipynb nb.ipynb.bak`. Verify: the backup exists.
2. Validate and capture the exact complaint: `python -c "import nbformat; nbformat.read('nb.ipynb', as_version=4)"`. Verify: the message names a cell index and field.
3. Open the file and inspect the named location. Verify: you can see the malformed structure (missing field, wrong type).
4. Repair the minimal structure: every cell needs `cell_type`, `metadata`, `source`, and for code cells `outputs` and `execution_count`. Verify: the shape matches a known-good cell.
5. Re-run the validation command. Verify: it reads cleanly, then open in Jupyter.

## Variant phrasings
### nbformat validation failed
Short form. The validator names the bad spot.

### notebook won't open after editing json
Symptom phrasing. Validate before reopening.

### NotebookValidationError cells
Schema-level phrasing. A cell lost a required field.

Compatibility: nbformat 5.x, notebook 6/7, JupyterLab 3/4. The v4 schema requirements are stable.

## Why it happens
The .ipynb format is JSON plus a strict schema: cell types, required fields, output shapes. Text editors do not know the schema, so a well-meaning edit like deleting a `metadata` object or leaving a trailing comma produces a file that is valid JSON but an invalid notebook. Jupyter validates on open and refuses the file rather than guessing.

## Edge cases / pitfalls
- Fixing JSON syntax is not the same as fixing schema validity. A file can parse and still fail validation.
- The validator reports the first failure only. Re-validate after each fix; there are often several.
- Merging notebooks by concatenating cell arrays by hand duplicates cell ids. Regenerate ids or let nbformat handle the merge.
- If the damage is extensive, extract the good cells programmatically with nbformat into a fresh notebook instead of hand-repairing.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_oH5I5sAqkR-bS8JjNXwzxg
