jackwener/OpenCLI · error · CommandExecutionError
NotebookLM page-state probe returned malformed Browser Bridg
Error message
NotebookLM page-state probe returned malformed Browser Bridge data
What it means
getNotebooklmPageState injects a probe script via the Browser Bridge that must return a plain object with typed fields (url, title, hostname, kind, notebookId, loginRequired, notebookCount). If the returned raw value is not an object or any field has the wrong type, this CommandExecutionError is thrown. It guards against the injected script failing, being blocked, or returning null/garbage so downstream URL classification never operates on bad data.
Source
Thrown at clis/notebooklm/utils.js:671
const textNodes = Array.from(document.querySelectorAll('a, button, [role="button"], h1, h2'))
.map(node => (node.textContent || '').trim().toLowerCase())
.filter(Boolean);
const loginRequired = path === '/login' || path.startsWith('/login/') || textNodes.some(text =>
text.includes('sign in') ||
text.includes('log in') ||
text.includes('登录') ||
text.includes('登入')
);
const notebookCount = Array.from(document.querySelectorAll('a[href*="/notebook/"]'))
.map(node => node instanceof HTMLAnchorElement ? node.href : '')
.filter(Boolean)
.reduce((count, href, index, list) => list.indexOf(href) === index ? count + 1 : count, 0);
return { url, title, hostname, kind, notebookId, loginRequired, notebookCount, path };
})()`, 'page-state probe');
if (!isPlainObject(raw) || typeof raw.url !== 'string' || typeof raw.title !== 'string' || typeof raw.hostname !== 'string' || typeof raw.kind !== 'string' || typeof raw.notebookId !== 'string' || typeof raw.loginRequired !== 'boolean' || typeof raw.notebookCount !== 'number' || !Number.isFinite(raw.notebookCount)) {
throw new CommandExecutionError('NotebookLM page-state probe returned malformed Browser Bridge data');
}
let parsed;
try {
parsed = new URL(raw.url);
}
catch {
throw new CommandExecutionError('NotebookLM page-state probe returned an invalid URL');
}
if (parsed.hostname !== raw.hostname) {
throw new CommandExecutionError('NotebookLM page-state probe returned inconsistent URL and hostname fields');
}
const trusted = parseTrustedNotebooklmUrl(parsed.href);
const kind = trusted ? classifyNotebooklmPage(trusted.href) : 'unknown';
const notebookId = kind === 'notebook' ? parseNotebooklmIdFromUrl(trusted.href) : '';
const loginPath = Boolean(trusted && (trusted.pathname === '/login' || trusted.pathname.startsWith('/login/')));
const state = {
url: raw.url,
title: normalizeNotebooklmTitle(raw?.title, 'NotebookLM'),View on GitHub (pinned to 49907e53dc)
Solutions
- Reload the NotebookLM page and retry the state probe
- Confirm the page is actually on notebooklm.google.com (check page.url()) before probing
- Re-launch or re-attach the browser/Bridge if the tab crashed
- Update the library if NotebookLM's page structure changed the probe inputs
- Add a wait for page readiness (network idle / selector) before probing
Example fix
// before
const state = await getNotebooklmPageState(page);
// after: pre-validate location and retry on malformed probe
if (!page.url().includes('notebooklm.google.com')) await openNotebooklmHome(page);
let state;
try { state = await getNotebooklmPageState(page); }
catch (e) {
if (!/malformed Browser Bridge data/.test(e.message)) throw e;
await page.reload();
state = await getNotebooklmPageState(page);
} Defensive patterns
Strategy: type-guard
Validate before calling
function isValidPageState(raw) {
return raw !== null && typeof raw === 'object'
&& typeof raw.url === 'string'
&& typeof raw.title === 'string'
&& typeof raw.hostname === 'string'
&& typeof raw.kind === 'string'
&& typeof raw.notebookId === 'string'
&& typeof raw.loginRequired === 'boolean'
&& typeof raw.notebookCount === 'number'
&& Number.isFinite(raw.notebookCount);
} Type guard
function isNotebooklmPageState(v) {
return v !== null && typeof v === 'object' && typeof v.url === 'string'
&& typeof v.hostname === 'string' && typeof v.notebookCount === 'number'
&& Number.isFinite(v.notebookCount) && typeof v.loginRequired === 'boolean';
} Try / catch
try {
const state = await getNotebooklmPageState(page);
} catch (e) {
if (!/malformed Browser Bridge data/.test(e.message)) throw e;
await page.reload(); // recover from error page / interrupted navigation
const state = await getNotebooklmPageState(page);
} Prevention
- Confirm page.url() is on notebooklm.google.com before probing
- Wait for page readiness (selector/network idle) before running the probe
- Reload after crashes or error pages — probes fail on synthetic pages
- Keep the library updated for NotebookLM page-structure changes
- Avoid probing during active navigation
When it happens
Trigger: Calling getNotebooklmPageState when the evaluated probe returns non-object data — the page is on a chrome error page or about:blank, content script evaluation is blocked (CSP/extension), the browser bridge returns undefined on failure, or NotebookLM's page structure changed so a probe variable is undefined.
Common situations: Browser on an error/crash page instead of NotebookLM; navigation interrupted mid-probe; Browser Bridge desync after tab crash; future NotebookLM redesign removing fields the probe reads; headless environment quirks.
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 page auth probe returned malformed fields
- NotebookLM page-state probe returned an invalid URL
- Gmail batch-view response had an unexpected shape
- 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/374eb09d742b1429.
Report an issue: GitHub.