jackwener/OpenCLI · error · CommandExecutionError
NotebookLM home-link probe returned a malformed row
Error message
NotebookLM home-link probe returned a malformed row
What it means
Each entry from the home-link probe must be a plain object with string id/title/url, optional string created_at, and optional boolean is_owner. The CLI validates every row individually; the first row violating this shape triggers this CommandExecutionError so corrupt or unexpected rows never reach command output.
Source
Thrown at clis/notebooklm/utils.js:797
).trim();
rows.push({
id,
title,
url: href,
source: 'home-links',
is_owner: true,
created_at: createdAtHint || null,
});
}
return rows;
})()`, 'home-link probe');
if (!Array.isArray(raw))
throw new CommandExecutionError('NotebookLM home-link probe returned malformed Browser Bridge data');
return raw.map((row) => {
if (!isPlainObject(row) || typeof row.id !== 'string' || typeof row.title !== 'string' || typeof row.url !== 'string' || (row.created_at !== null && row.created_at !== undefined && typeof row.created_at !== 'string') || (row.is_owner !== undefined && typeof row.is_owner !== 'boolean')) {
throw new CommandExecutionError('NotebookLM home-link probe returned a malformed row');
}
const url = normalizeNotebooklmNotebookUrl(row.url, row.id);
if (!url) {
throw new CommandExecutionError('NotebookLM home-link probe returned an untrusted or mismatched notebook URL');
}
return {
id: row.id,
title: normalizeNotebooklmTitle(row.title, 'Untitled Notebook'),
url,
source: 'home-links',
is_owner: row.is_owner === false ? false : true,
created_at: normalizeNotebooklmCreatedAt(row.created_at),
};
});
}
export async function listNotebooklmSourcesFromPage(page) {
const raw = unwrapNotebooklmEvaluateResult(await page.evaluate(`(() => {
const notebookMatch = window.location.href.match(/\\/notebook\\/([^/?#]+)/);View on GitHub (pinned to 49907e53dc)
Solutions
- Reload the NotebookLM home page and re-run the probe to get freshly parsed rows.
- Update the CLI to a version matching the current NotebookLM DOM structure.
- Clear extension/page state (disable other extensions that mutate the DOM) and retry.
- If you control the probe script, log the offending row to see which field violates the contract before fixing the extractor.
Example fix
// before: trusting all rows for (const row of raw) addNotebook(row.id, row.title); // after: validating rows const safeRows = raw.filter(r => r && typeof r.id === 'string' && typeof r.title === 'string' && typeof r.url === 'string'); safeRows.forEach(r => addNotebook(r.id, r.title));
Defensive patterns
Strategy: type-guard
Validate before calling
const validRow = (r) => r !== null && typeof r === 'object' && typeof r.id === 'string' && typeof r.title === 'string' && typeof r.url === 'string' && (r.created_at == null || typeof r.created_at === 'string') && (r.is_owner === undefined || typeof r.is_owner === 'boolean');
if (Array.isArray(raw) && !raw.every(validRow)) throw new Error('Probe returned a malformed row; reload the NotebookLM home page.'); Type guard
function isNotebookRow(v) {
return typeof v === 'object' && v !== null && !Array.isArray(v) &&
typeof v.id === 'string' && typeof v.title === 'string' && typeof v.url === 'string';
} Try / catch
try {
rows = await probeHomeLinks();
} catch (e) {
if (String(e.message).includes('malformed row')) {
console.error('NotebookLM markup may have changed; reload the page or update the CLI.');
} else { throw e; }
} Prevention
- Reload the home page before probing so rows are freshly parsed.
- Disable extensions that inject DOM elements into NotebookLM pages.
- Keep the CLI updated against NotebookLM UI changes.
- Validate rows client-side and skip (or log) invalid ones during development.
When it happens
Trigger: A row in the probe's returned array is not a plain object or has a field of the wrong type — e.g. missing title after a UI change, created_at as a number timestamp, is_owner as string "true", or a null entry inside the array.
Common situations: NotebookLM markup updates introducing new/renamed attributes scraped into rows, pinned/section headers being captured as pseudo-rows, or locale changes altering field extraction.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- NotebookLM current-page probe returned malformed Browser Bri
- NotebookLM home-link probe returned malformed Browser Bridge
- Unexpected NotebookLM probe: ${JSON.stringify(probe)}
- NotebookLM ${label} returned a malformed Browser Bridge payl
- NotebookLM ${label} failed: ${error?.message || error}
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/bc95668083a1ec1f.
Report an issue: GitHub.