{"record":{"id":"bc95668083a1ec1f","repo":"jackwener/OpenCLI","slug":"notebooklm-home-link-probe-returned-a-malformed-ro","errorCode":null,"errorMessage":"NotebookLM home-link probe returned a malformed row","messagePattern":"NotebookLM home-link probe returned a malformed row","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/notebooklm/utils.js","lineNumber":797,"sourceCode":"      ).trim();\n\n      rows.push({\n        id,\n        title,\n        url: href,\n        source: 'home-links',\n        is_owner: true,\n        created_at: createdAtHint || null,\n      });\n    }\n\n    return rows;\n  })()`, 'home-link probe');\n    if (!Array.isArray(raw))\n        throw new CommandExecutionError('NotebookLM home-link probe returned malformed Browser Bridge data');\n    return raw.map((row) => {\n        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')) {\n            throw new CommandExecutionError('NotebookLM home-link probe returned a malformed row');\n        }\n        const url = normalizeNotebooklmNotebookUrl(row.url, row.id);\n        if (!url) {\n            throw new CommandExecutionError('NotebookLM home-link probe returned an untrusted or mismatched notebook URL');\n        }\n        return {\n        id: row.id,\n        title: normalizeNotebooklmTitle(row.title, 'Untitled Notebook'),\n        url,\n        source: 'home-links',\n        is_owner: row.is_owner === false ? false : true,\n        created_at: normalizeNotebooklmCreatedAt(row.created_at),\n        };\n    });\n}\nexport async function listNotebooklmSourcesFromPage(page) {\n    const raw = unwrapNotebooklmEvaluateResult(await page.evaluate(`(() => {\n    const notebookMatch = window.location.href.match(/\\\\/notebook\\\\/([^/?#]+)/);","sourceCodeStart":779,"sourceCodeEnd":815,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/notebooklm/utils.js#L779-L815","documentation":"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.","triggerScenarios":"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.","commonSituations":"NotebookLM markup updates introducing new/renamed attributes scraped into rows, pinned/section headers being captured as pseudo-rows, or locale changes altering field extraction.","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."],"exampleFix":"// before: trusting all rows\nfor (const row of raw) addNotebook(row.id, row.title);\n\n// after: validating rows\nconst safeRows = raw.filter(r => r && typeof r.id === 'string' && typeof r.title === 'string' && typeof r.url === 'string');\nsafeRows.forEach(r => addNotebook(r.id, r.title));","handlingStrategy":"type-guard","validationCode":"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');\nif (Array.isArray(raw) && !raw.every(validRow)) throw new Error('Probe returned a malformed row; reload the NotebookLM home page.');","typeGuard":"function isNotebookRow(v) {\n  return typeof v === 'object' && v !== null && !Array.isArray(v) &&\n    typeof v.id === 'string' && typeof v.title === 'string' && typeof v.url === 'string';\n}","tryCatchPattern":"try {\n  rows = await probeHomeLinks();\n} catch (e) {\n  if (String(e.message).includes('malformed row')) {\n    console.error('NotebookLM markup may have changed; reload the page or update the CLI.');\n  } else { throw e; }\n}","preventionTips":["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."],"tags":["notebooklm","schema-validation-failed","probe","browser-bridge"],"backgroundTag":"row-schema-validation-failed","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}