jackwener/OpenCLI · error · CommandExecutionError

NotebookLM page-state probe returned inconsistent URL and ho

Error message

NotebookLM page-state probe returned inconsistent URL and hostname fields

What it means

After parsing the probe URL, getNotebooklmPageState cross-checks that parsed.hostname equals the separately reported raw.hostname field; a mismatch throws this CommandExecutionError. This consistency check catches probe data where url and hostname disagree — evidence the probe output was assembled incorrectly, intercepted, or spoofed, so the library refuses to trust it for URL classification.

Source

Thrown at clis/notebooklm/utils.js:681

    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'),
        hostname: raw.hostname,
        kind,
        notebookId,
        loginRequired: loginPath || raw.loginRequired,
        notebookCount: Math.max(0, raw.notebookCount),
    };
    // Notebook pages can still contain "sign in" or login-related text fragments
    // even when the active Google session is valid. Prefer the real page tokens
    // as the stronger auth signal before declaring the session unauthenticated.
    if (isNotebooklmHost(state.hostname) && state.loginRequired && !loginPath) {

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Retry the probe after navigation settles (wait for load/idle) — races between reads are the usual cause
  2. Reload the NotebookLM page and re-run getNotebooklmPageState
  3. Disable browser extensions/proxies that rewrite location and retry
  4. Update the library so url and hostname are captured atomically from the parsed URL rather than separately
  5. Manually confirm the final URL in the browser to check for unexpected redirects

Example fix

// before: two independent reads in probe
return { url: window.location.href, hostname: window.location.hostname, ... };
// after: derive both from one value
const url = window.location.href;
return { url, hostname: new URL(url).hostname, ... };
Defensive patterns

Strategy: validation

Validate before calling

function hostnameMatches(state) {
  try { return new URL(state.url).hostname === state.hostname; }
  catch { return false; }
}
// after obtaining state, before trusting it:
if (!hostnameMatches(state)) {
  await page.reload();
  // re-fetch state
}

Type guard

function hasConsistentHost(v) {
  if (typeof v?.url !== 'string' || typeof v?.hostname !== 'string') return false;
  try { return new URL(v.url).hostname === v.hostname; } catch { return false; }
}

Try / catch

try {
  const state = await getNotebooklmPageState(page);
} catch (e) {
  if (!/inconsistent URL and hostname/.test(e.message)) throw e;
  await page.waitForLoadState?.('load') ?? await page.wait(2); // let navigation settle
  const state = await getNotebooklmPageState(page);
}

Prevention

When it happens

Trigger: getNotebooklmPageState when the probe's hostname field differs from the hostname of raw.url — e.g. a redirect happened between the two reads, an extension modified one of them, or the probe script was altered/failed partially so stale or wrong values were captured.

Common situations: Mid-navigation race where location changed between field reads; security tooling or extensions rewriting location fields; a modified/custom probe returning inconsistent data; unusual redirects between google.com subdomains during login flows.

Related errors


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