jackwener/OpenCLI · error · ArgumentError

--recipient must be a Sales Navigator lead URL, Sales Naviga

Error message

--recipient must be a Sales Navigator lead URL, Sales Navigator profile URL, LinkedIn /in/ URL, or urn:li:fs_salesProfile:(...)

What it means

resolveRecipient throws ArgumentError when the --recipient argument could not be parsed into any supported form (Sales Nav lead URN, Sales Nav lead URL, /in/ profile URL, or a resolvable salesProfile urn). parseRecipient returned null/undefined for the supplied value.

Source

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

  return result;
}

function salesPageShowsSentMessage(text, recipientName) {
  const normalizedText = normalizeWhitespace(text);
  const firstName = normalizeWhitespace(recipientName).split(' ')[0];
  return normalizedText.includes('You sent a Sales Navigator message')
    && (!firstName || normalizedText.includes(firstName));
}

async function getCsrf(page) {
  const cookies = await page.getCookies({ url: 'https://www.linkedin.com' });
  const jsession = cookies.find((c) => c.name === 'JSESSIONID')?.value;
  if (!jsession) throw new AuthRequiredError(LINKEDIN_DOMAIN, 'LinkedIn JSESSIONID cookie not found. Please sign in to LinkedIn.');
  return jsession.replace(/^\"|\"$/g, '');
}

async function resolveRecipient(page, parsed, csrf) {
  if (!parsed) throw new ArgumentError('--recipient must be a Sales Navigator lead URL, Sales Navigator profile URL, LinkedIn /in/ URL, or urn:li:fs_salesProfile:(...)');
  if (parsed.entityUrn && parsed.authType && parsed.authToken) return parsed;

  await page.goto(`https://www.linkedin.com/sales/lead/${encodeURIComponent(parsed.profileId)}`);
  await page.wait(6);
  const probe = unwrapEvaluateResult(await page.evaluate(String.raw`(() => {
    const href = location.href;
    const text = document.body ? document.body.innerText : '';
    const resourceUrns = Array.from(performance.getEntriesByType('resource'))
      .map((entry) => entry.name)
      .filter((name) => name.includes('/sales-api/salesApiProfiles/'))
      .slice(-20);
    return { href, text: text.slice(0, 1000), resourceUrns };
  })()`));
    const urlMatch = String(probe?.href || '').match(/\/sales\/lead\/([^,/]+),([^,/]+),([^/?#]+)/i);
  if (urlMatch && isResolvedSalesProfileParts(urlMatch[1], urlMatch[2], urlMatch[3])) {
    return {
      profileId: decodeURIComponent(urlMatch[1]),
      authType: decodeURIComponent(urlMatch[2]),

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Provide a valid Sales Navigator lead URL, LinkedIn /in/ URL, or full urn:li:fs_salesProfile:(id,authType,authToken)
  2. Copy the URN from Sales Navigator (not a regular LinkedIn feed URL)
  3. Ensure all three urn segments are present and not 'undefined'/'null'
  4. Quote the argument in your shell to avoid truncation

Example fix

// before
--recipient "Jane Doe"
// after
--recipient "https://www.linkedin.com/in/jane-doe/"
Defensive patterns

Strategy: validation

Validate before calling

const RE = /^urn:li:fs_salesProfile:\(([^,()]+),([^,()]+),([^,()]+)\)$/;
const SALES_URL = /^https:\/\/www\.linkedin\.com\/sales\/lead\/[^,/]+,[^,/]+,[^/]+\/?$/i;
const IN_URL = /^https:\/\/www\.linkedin\.com\/in\/[^/]+\/?$/i;
if (!(RE.test(v) || SALES_URL.test(v) || IN_URL.test(v))) throw new Error('Unsupported --recipient format: ' + v);

Type guard

const isValidRecipient = (v) =>
  typeof v === 'string' && (
    /^urn:li:fs_salesProfile:\([^,()]+,[^,()]+,[^,()]+\)$/.test(v.trim()) ||
    /^https:\/\/(www\.)?linkedin\.com\/(sales\/lead\/[^/]+|in\/[^/]+)\/?$/i.test(v.trim())
  );

Try / catch

try {
  await sendMessage(page, { recipient: argv.recipient });
} catch (err) {
  if (err instanceof ArgumentError && err.message.startsWith('--recipient')) {
    console.error('Use a Sales Nav lead URL, /in/ URL, or full salesProfile urn');
  } else throw err;
}

Prevention

When it happens

Trigger: Passing --recipient values like a plain name, a non-https URL, a non-LinkedIn URL, a malformed urn:li:fs_salesProfile triple (missing parts or 'undefined'/'null' placeholders), or forgetting the flag entirely (requireStringArg yields nothing to parse).

Common situations: Copying a public LinkedIn company URL instead of a person profile; pasting a truncated URN; using a sales lead URL with placeholder auth segments; typos or extra whitespace/quotes in the argument.

Related errors


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