{"record":{"id":"20f828a4cccf39e6","repo":"jackwener/OpenCLI","slug":"notebooklm-page-state-probe-returned-an-invalid-ur","errorCode":null,"errorMessage":"NotebookLM page-state probe returned an invalid URL","messagePattern":"NotebookLM page-state probe returned an invalid URL","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/notebooklm/utils.js","lineNumber":678,"sourceCode":"      text.includes('登入')\n    );\n\n    const notebookCount = Array.from(document.querySelectorAll('a[href*=\"/notebook/\"]'))\n      .map(node => node instanceof HTMLAnchorElement ? node.href : '')\n      .filter(Boolean)\n      .reduce((count, href, index, list) => list.indexOf(href) === index ? count + 1 : count, 0);\n\n    return { url, title, hostname, kind, notebookId, loginRequired, notebookCount, path };\n  })()`, 'page-state probe');\n    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)) {\n        throw new CommandExecutionError('NotebookLM page-state probe returned malformed Browser Bridge data');\n    }\n    let parsed;\n    try {\n        parsed = new URL(raw.url);\n    }\n    catch {\n        throw new CommandExecutionError('NotebookLM page-state probe returned an invalid URL');\n    }\n    if (parsed.hostname !== raw.hostname) {\n        throw new CommandExecutionError('NotebookLM page-state probe returned inconsistent URL and hostname fields');\n    }\n    const trusted = parseTrustedNotebooklmUrl(parsed.href);\n    const kind = trusted ? classifyNotebooklmPage(trusted.href) : 'unknown';\n    const notebookId = kind === 'notebook' ? parseNotebooklmIdFromUrl(trusted.href) : '';\n    const loginPath = Boolean(trusted && (trusted.pathname === '/login' || trusted.pathname.startsWith('/login/')));\n    const state = {\n        url: raw.url,\n        title: normalizeNotebooklmTitle(raw?.title, 'NotebookLM'),\n        hostname: raw.hostname,\n        kind,\n        notebookId,\n        loginRequired: loginPath || raw.loginRequired,\n        notebookCount: Math.max(0, raw.notebookCount),\n    };\n    // Notebook pages can still contain \"sign in\" or login-related text fragments","sourceCodeStart":660,"sourceCodeEnd":696,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/notebooklm/utils.js#L660-L696","documentation":"After the page-state probe passes shape validation, the code attempts new URL(raw.url); if the URL string returned by the in-page probe cannot be parsed, this CommandExecutionError is thrown. The probe's url field should always be window.location.href, so an unparseable value means the probe returned corrupted or fabricated data.","triggerScenarios":"getNotebooklmPageState receiving raw.url that is not a valid absolute URL — e.g. an empty string, a relative path, or injected/intercepted navigation states where location.href is unusual; only reachable after the typeof check passed, so the string exists but is malformed.","commonSituations":"Browser stuck on a synthetic/interstitial page with odd location values; proxy or extension rewriting location.href; a library/NotebookLM change that makes the probe read a wrong variable for url.","solutions":["Reload the page and re-run the probe — transient navigation states often resolve","Log raw.url at the failure point to see what the probe actually returned","Ensure no extensions/proxies rewrite window.location on the page","Verify the probe script reads window.location.href (update library if NotebookLM changed)","Navigate explicitly to the NotebookLM home URL before probing"],"exampleFix":"// before\nconst state = await getNotebooklmPageState(page);\n// after: validate URL parseability defensively\nconst state = await getNotebooklmPageState(page);\nlet parsed;\ntry { parsed = new URL(state.url); }\ncatch {\n  await page.goto('https://notebooklm.google.com/');\n  // re-fetch state after a known-good navigation\n}\n","handlingStrategy":"type-guard","validationCode":"function isParseableUrl(u) {\n  try { new URL(u); return true; } catch { return false; }\n}\n// after obtaining state:\nif (!isParseableUrl(state.url)) {\n  await page.goto('https://notebooklm.google.com/'); // recover before proceeding\n}","typeGuard":"function isAbsoluteUrl(v) {\n  if (typeof v !== 'string') return false;\n  try { const u = new URL(v); return u.protocol === 'https:'; } catch { return false; }\n}","tryCatchPattern":"try {\n  const state = await getNotebooklmPageState(page);\n} catch (e) {\n  if (!/invalid URL/.test(e.message)) throw e;\n  await page.goto('https://notebooklm.google.com/');\n  const state = await getNotebooklmPageState(page); // re-probe after known-good navigation\n}","preventionTips":["Log the raw url value when this fires to spot rewriting by extensions/proxies","Navigate explicitly to a known-good NotebookLM URL before probing","Disable location-rewriting browser extensions in automation environments","Validate URL parseability immediately after receiving probe data","Re-probe after redirects settle (login flows change location)"],"tags":["notebooklm","page-state","url-parsing","browser-bridge"],"backgroundTag":"page-state-probe-malformed","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}