jackwener/OpenCLI · error · CommandExecutionError

Browser session required for linkedin salesnav-message

Error message

Browser session required for linkedin salesnav-message

What it means

The salesnav-message CLI command requires a live browser page (it navigates Sales Navigator and reads cookies). The command function throws CommandExecutionError immediately if page is falsy — i.e. the command was invoked outside a browser session context.

Source

Thrown at clis/linkedin/salesnav-message.js:267

cli({
  site: 'linkedin',
  name: 'salesnav-message',
  access: 'write',
  description: 'Send or dry-run a LinkedIn Sales Navigator InMail to a lead using the Sales Navigator messaging API',
  domain: LINKEDIN_DOMAIN,
  strategy: Strategy.UI,
  browser: true,
  args: [
    { name: 'recipient', type: 'string', required: true, positional: true, help: 'Sales Navigator lead URL, LinkedIn /in/ URL from salesnav-search, or urn:li:fs_salesProfile:(...)' },
    { name: 'subject', type: 'string', required: true, help: 'InMail subject' },
    { name: 'body', type: 'string', required: true, help: 'InMail body' },
    { name: 'send', type: 'bool', default: false, help: 'Actually send the InMail. Default is dry-run validation only.' },
    { name: 'copy-to-crm', type: 'bool', default: false, help: 'Set Sales Navigator copyToCrm on the message request' },
  ],
  columns: ['status', 'recipient', 'title', 'company', 'credits_remaining', 'credits_before', 'credits_after', 'sent_in_salesnav', 'message_chars', 'subject_chars', 'recipient_urn', 'degree', 'inmail_restriction', 'open_link'],
  func: async (page, args) => {
    if (!page) throw new CommandExecutionError('Browser session required for linkedin salesnav-message');
    const recipientArg = requireStringArg(args, 'recipient', '--recipient');
    const subject = requireStringArg(args, 'subject', '--subject');
    const body = String(args.body ?? '').trim();
    if (!body) throw new ArgumentError('--body is required');

    await page.goto(SALES_HOME);
    await page.wait(4);
    const csrf = await getCsrf(page);
    const recipient = await resolveRecipient(page, parseRecipient(recipientArg), csrf);

    let summary = { recipient: '', title: '', company: '', degree: '', inmail_restriction: '', open_link: false };
    const profileUrl = profileApiUrl(recipient);
    if (profileUrl) {
      const profileResult = requireFetchResult(unwrapEvaluateResult(await page.evaluate(fetchJsonScript(profileUrl, csrf))), 'LinkedIn Sales Navigator profile API');
      summary = requireProfileSummary(profileResult.json);
    }
    if (summary.inmail_restriction && summary.inmail_restriction !== 'NO_RESTRICTION') {
      throw new CommandExecutionError('Sales Navigator InMail blocked by recipient restriction', summary.inmail_restriction);

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Launch/attach a browser session before running the command
  2. Use the CLI's normal browser-backed invocation path
  3. Verify your runner passes the page argument to the command func
  4. Check for browser launch failures earlier in the logs

Example fix

// before
await registry.run('linkedin', 'salesnav-message', null, args);
// after
const page = await browser.newPage();
await registry.run('linkedin', 'salesnav-message', page, args);
Defensive patterns

Strategy: validation

Validate before calling

if (!page) throw new Error('salesnav-message needs a browser page — launch the browser session first');

Type guard

const hasBrowserPage = (page) => page != null && typeof page.goto === 'function' && typeof page.evaluate === 'function';

Try / catch

try {
  await cli.run('linkedin', 'salesnav-message', page, args);
} catch (err) {
  if (/Browser session required/.test(err.message)) {
    console.error('Start the browser (e.g. `opencli browser start`) and retry');
  } else throw err;
}

Prevention

When it happens

Trigger: Calling the registered 'linkedin salesnav-message' command without an attached/launched browser, or from a non-browser execution mode where func receives page=null.

Common situations: Running the CLI in headless-API mode without launching the browser; forgetting the browser launch/start step; wiring the command into a batch runner that doesn't provision pages.

Related errors


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