Troubleshooting

An index of the messages go tool notebook check, run, and build emit, what each means, and the fix. Most map directly to one of the rules that bite.


Wiring and graph errors

cell "X" needs p T, but no cell produces it. A cell takes a parameter that no other cell produces as a result. Either the producer’s result name/type doesn’t match, or you meant to make the parameter an input. If check adds “Did you mean Y, which produces T?”, that cell produces the right type under a different name — rename one to match. Remember the edge is the result name, not the function name (how names work).

cell "X" produces r T, but r is already produced by cell "Y". Two cells return a result with the same name. A result name is an edge, and edges must be unique. Give one a different name.

cell "X" takes p T, but cell "Y" produces pasU. The names match but the types don’t (p int vs p float64). An edge matches on both name and type. Make the types agree, or rename one side so they are deliberately distinct edges.

cycle among cells: A → B → A. Cells depend on each other in a loop. The graph must be acyclic — a value cannot depend on itself, even transitively. A stateful feedback loop would need Prev[T] folds, which are not supported yet; restructure as a one-directional computation (often a fixed-horizon pure cell that computes all steps at once).

“My function isn’t showing up”

A top-level function is missing from the graph. It produces no named result, so it is treated as an ordinary helper and left out (this is intentional — it’s how you write helpers). check lists such functions under “helpers (not cells — they name no result)”. To make it a cell, name its result: func f() (out T), not func f() T.

cell "X" has an unnamed result; cell results must be named — the name is the edge. A cell named some results but left a non-error result unnamed. Name every result, or leave them all unnamed to make it a helper.

A function I documented still isn’t a cell. The doc comment does not make a cell — a named result does. A documented function with unnamed returns is still a helper. (See how names work.)

Rich output not appearing

A cell computes a value but shows nothing. A composite (a struct or slice) with no Render() method stays hidden by design — never a broken box. To draw it, give its type a Render() method returning a {MIME, Data} value (rendering). A bare scalar always shows as a readout; only non-scalars without a Render are hidden.

cell "X" has a Render() method, but …; it will not render. The Render() method exists but its shape is wrong. The probe requires Render() taking no arguments and returning one struct with string fields named exactly MIME and Data (case-sensitive — MIME, not Mime). The message names the specific mismatch.

WASM / browser build

"pkg" is not WASM-able. These cells transitively touch net/os/cgo … A cell’s call graph reaches net, os, or cgo, which have no browser form. That notebook can still build as a native binary; it just can’t compile to WASM. Move the offending work out of the cell, or accept it as native-only.

A cell that only formats a number is flagged as not WASM-able. fmt transitively reaches os, and the portability gate is a conservative over-approximation of the call graph — so fmt in a cell body trips it even when no real I/O happens (the tool says so: “flagged conservatively via fmt→os”). Fix: move formatting into a Render() method (which is not a cell), or use strconv if a cell body genuinely must format a number.

A built WASM page is blank, or the console shows a fetch/CORS error. WASM must be served over HTTP, not opened as a file:// path. Serve the build directory: (cd site && python3 -m http.server 8080) then open http://localhost:8080.

Package and file errors

no //go:notebook file found No file in the package carries the //go:notebook marker. Add it as a comment line at the top of your notebook file.

package has more than one //go:notebook file Exactly one file per package carries the marker; the rest of the package is ordinary Go (helpers, types, tests split across files are fine — just one file gets //go:notebook).

Stale results

Edits don’t take effect / an old value persists. run rebuilds on save; if a served value looks stale, confirm the save landed and the rebuild finished (the terminal logs it). A built binary loads a persisted head file (notebook-head.json by default) — a leftover head can inject old input values. Pass --head <fresh-path> to start clean, or delete the stale head file. Built artifacts are content-addressed (the WASM filename carries a hash of the source), so a genuinely new build never collides with a cached old one.