can1357/oh-my-pi · error

Invalid notebook editable representation for ${displayPath}:

Error message

Invalid notebook editable representation for ${displayPath}: expected first line to be "# %% [code] cell:0", "# %% [markdown] cell:0", or "# %% [raw] cell:0".

What it means

parseNotebookEditableText converts an editable virtual-text representation of a Jupyter notebook (cells prefixed with '# %% [code|markdown|raw] cell:N' markers) back into cells. The very first line of the payload must be a cell marker; if any line appears before any marker has been seen, the payload does not start with a cell header and cannot be mapped onto notebook cells.

Source

Thrown at packages/coding-agent/src/edit/notebook.ts:175

	const flush = () => {
		if (!current) return;
		cells.push({
			cellType: current.cellType,
			cellIndex: current.cellIndex,
			source: linesToSourceText(current.lines),
		});
	};

	for (const line of lines) {
		const marker = parseVirtualCellMarker(line);
		if (marker) {
			flush();
			current = { ...marker, lines: [] };
			continue;
		}
		if (!current) {
			throw new Error(
				`Invalid notebook editable representation for ${displayPath}: expected first line to be "# %% [code] cell:0", "# %% [markdown] cell:0", or "# %% [raw] cell:0".`,
			);
		}
		current.lines.push(unescapeMarkerLikeLine(line));
	}
	flush();
	return cells;
}

export function applyNotebookEditableText(
	notebook: NotebookDocument,
	text: string,
	displayPath: string,
): NotebookDocument {
	const parsedCells = parseNotebookEditableText(text, displayPath);
	const usedOriginalCells = new Set<number>();
	const nextNotebook = structuredClone(notebook);
	nextNotebook.cells = parsedCells.map(parsedCell => {

View on GitHub (pinned to 9690622007)

Solutions

  1. Prefix the payload with a valid first-cell marker such as '# %% [code] cell:0' before the first content line
  2. Re-read the notebook via readEditFileText to get a canonical editable representation and re-apply the edit on top of it
  3. Verify the payload was not truncated or line-shifted (e.g. by a patch tool) and regenerate it

Example fix

// before
"print('hello')"
// after
"# %% [code] cell:0\nprint('hello')"
Defensive patterns

Strategy: validation

Validate before calling

const firstLine = text.split('\n', 1)[0];
if (!/^# %% \[(code|markdown|raw)\]( cell:\d+)?$/.test(firstLine.trim())) {
  throw new Error(`payload must start with a cell marker, got: ${firstLine.slice(0, 60)}`);
}

Type guard

function startsWithCellMarker(text: string): boolean {
  return /^# %% \[(code|markdown|raw)\] cell:\d+/.test(text.split('\n', 1)[0]);
}

Try / catch

try {
  await editNotebook(path, payload);
} catch (err) {
  if (err instanceof Error && err.message.includes('Invalid notebook editable representation')) {
    payload = `# %% [code] cell:0\n${payload}`;
    await editNotebook(path, payload);
  } else throw err;
}

Prevention

When it happens

Trigger: Calling applyNotebookEditableText (via the edit/write tool on a .ipynb path) with text whose first line is not a cell marker — e.g. raw cell source pasted without the '# %% [code] cell:0' header, a truncated payload whose marker line was lost, or a payload starting with a blank line or comment.

Common situations: An LLM or script writing notebook edits omits the marker header and writes cell content directly; the notebook was manually hand-edited in the virtual view and the first marker was deleted; a diff/patch dropped the first line.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/6856f5d042b96542. Report an issue: GitHub.