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

  1. Reload the NotebookLM home page and re-run the probe to get freshly parsed rows.
  2. Update the CLI to a version matching the current NotebookLM DOM structure.
  3. Clear extension/page state (disable other extensions that mutate the DOM) and retry.
  4. 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

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

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/bc95668083a1ec1f. Report an issue: GitHub.