jackwener/OpenCLI · error · CommandExecutionError

Browser session required for linkedin thread-snapshot

Error message

Browser session required for linkedin thread-snapshot

What it means

The thread-snapshot command runs a real browser page to open the thread, scroll, and intercept messengerMessages API responses. It throws this CommandExecutionError when the cli func is invoked with a null/undefined page, meaning no browser session was created or passed in.

Source

Thrown at clis/linkedin/thread-snapshot.js:313

  return { recipientNames, messages };
}

cli({
  site: 'linkedin',
  name: 'thread-snapshot',
  access: 'read',
  description: 'Load a LinkedIn messaging thread and return a structured conversation snapshot',
  domain: LINKEDIN_DOMAIN,
  strategy: Strategy.COOKIE,
  browser: true,
  args: [
    { name: 'thread-url', required: true, help: 'Exact LinkedIn messaging thread URL to open and snapshot' },
    { name: 'max-scrolls', type: 'number', default: 30, help: 'Maximum upward scroll attempts used to request older message pages' },
    { name: 'json', type: 'bool', default: false, help: 'Return only JSON snapshot string in the snapshot_json field' },
  ],
  columns: ['thread_url', 'recipient', 'message_count', 'latest_text', 'snapshot_json'],
  func: async (page, args) => {
    if (!page) throw new CommandExecutionError('Browser session required for linkedin thread-snapshot');
    const threadUrl = requireLinkedInThreadUrl(requireStringArg(args, 'thread-url', '--thread-url'), '--thread-url');
    const maxScrolls = parseMaxScrolls(args['max-scrolls']);

    await page.goto(threadUrl);
    await page.wait(10);

    let discovery = unwrapEvaluateResult(await page.evaluate(buildThreadApiDiscoveryScript(maxScrolls)));
    if (discovery && Array.isArray(discovery.apiUrls) && discovery.apiUrls.length === 0) {
      const firstDiscovery = discovery;
      await page.wait(4);
      const retried = unwrapEvaluateResult(await page.evaluate(buildThreadApiDiscoveryScript(0)));
      if (retried && typeof retried === 'object' && !Array.isArray(retried)) {
        discovery = {
          ...retried,
          scrollAttempts: firstDiscovery.scrollAttempts,
          scrollStable: firstDiscovery.scrollStable,
        };
      } else {

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Start/attach a browser session (with a signed-in LinkedIn profile) before invoking the command
  2. Check your runner/harness so browser:true commands receive a live page object
  3. If the session crashed, re-launch it and re-run the command
  4. In scripts, assert the page exists before calling the CLI func

Example fix

// before
await linkedinThreadSnapshot.func(null, args);
// after
const page = await browserSession.acquire('linkedin');
await linkedinThreadSnapshot.func(page, args);
Defensive patterns

Strategy: type-guard

Validate before calling

if (!page || typeof page.goto !== 'function') {
  throw new Error('Launch a browser session before running linkedin thread-snapshot');
}

Type guard

const hasLivePage = (page) => !!page && typeof page.goto === 'function' && typeof page.wait === 'function';

Try / catch

try {
  const snap = await run('linkedin thread-snapshot', { 'thread-url': url });
} catch (err) {
  if (String(err.message).includes('Browser session required')) {
    const page = await browserSession.acquire('linkedin');
    // retry with an allocated page
  } else throw err;
}

Prevention

When it happens

Trigger: Calling the command without an active browser session — e.g. invoking func directly with no page, or running through a harness that doesn't allocate a browser for browser:true commands.

Common situations: Forgetting to launch the browser session before executing the command in scripts/tests; a session pool exhausted or closed before the call; misconfigured runner that skips browser setup for LinkedIn commands.

Related errors


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