jackwener/OpenCLI · error · CommandExecutionError

Browser session required for linkedin services-read

Error message

Browser session required for linkedin services-read

What it means

The services-read command runs in a browser context and requires an active Playwright/puppeteer-style page. The command's func starts by checking the `page` argument and throws this CommandExecutionError if it is falsy — i.e. the command was invoked without a live browser session.

Source

Thrown at clis/linkedin/services-read.js:172

  await assertLinkedInAuthenticated(page, 'LinkedIn services-read edit');
  return unwrapEvaluateResult(await page.evaluate(buildServicesEditScript()));
}

cli({
  site: 'linkedin',
  name: 'services-read',
  access: 'read',
  description: 'Read LinkedIn Services page details including services, overview, availability, pricing, and media titles/descriptions',
  domain: 'www.linkedin.com',
  strategy: Strategy.COOKIE,
  browser: true,
  args: [
    { name: 'profile-url', type: 'string', required: false, help: 'LinkedIn /in/<handle>/ profile URL. Defaults to /in/me/.' },
    { name: 'services-url', type: 'string', required: false, help: 'LinkedIn /services/page/<id>/ URL. If omitted, it is discovered from the profile.' },
  ],
  columns: ['service_url', 'page_title', 'overview', 'availability', 'work_locations', 'pricing', 'services_provided', 'services_count', 'media', 'media_count', 'messages', 'reviews_visibility'],
  func: async (page, args) => {
    if (!page) throw new CommandExecutionError('Browser session required for linkedin services-read');
    let servicesUrl = normalizeWhitespace(args['services-url']);
    const shouldReadOwnerEdit = !servicesUrl && !normalizeWhitespace(args['profile-url']);
    if (servicesUrl) {
      servicesUrl = normalizeServicesUrl(servicesUrl);
    } else {
      await page.goto(normalizeProfileUrl(args['profile-url']));
      await page.wait(5);
      await assertLinkedInAuthenticated(page, 'LinkedIn services-read profile');
      const found = unwrapEvaluateResult(await page.evaluate(buildFindServicesUrlScript()));
      servicesUrl = normalizeWhitespace(found?.services_url);
      if (!servicesUrl) throw new EmptyResultError('linkedin services-read', 'No LinkedIn Services page link was found on the profile.');
      servicesUrl = normalizeServicesUrl(servicesUrl);
    }

    await page.goto(servicesUrl);
    await page.wait(5);
    await assertLinkedInAuthenticated(page, 'LinkedIn services-read');
    const services = unwrapEvaluateResult(await page.evaluate(buildServicesPageScript()));

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Ensure the CLI/browser session is started before running the command (same session flow used by other linkedin browser commands).
  2. Check upstream logs for browser launch failures (missing Chrome/Chromium, sandbox issues) that leave page null.
  3. In tests, pass a mock page object when calling the command func directly.
Defensive patterns

Strategy: validation

Validate before calling

if (!page || typeof page.goto !== 'function') {
  throw new Error('services-read requires an active browser page; start a browser session first');
}

Type guard

function hasBrowserPage(p) {
  return Boolean(p) && typeof p.goto === 'function' && typeof p.evaluate === 'function';
}

Prevention

When it happens

Trigger: Invoking linkedin services-read through a runner that does not provision a browser page (headless batch mode without a session, CLI wiring that skipped browser startup, or page creation failed upstream).

Common situations: Running the command via a non-interactive runner that passes null for page; browser launch failure silently swallowed upstream; calling the command's func directly in tests without a page fixture.

Related errors


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