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
- Provide a valid Sales Navigator lead URL, LinkedIn /in/ URL, or full urn:li:fs_salesProfile:(id,authType,authToken)
- Copy the URN from Sales Navigator (not a regular LinkedIn feed URL)
- Ensure all three urn segments are present and not 'undefined'/'null'
- 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
- Copy recipients straight from Sales Navigator, not the feed
- Ensure all three urn segments are populated (no 'undefined'/'null')
- Quote the flag value in shell to avoid truncation
- Reject non-https or non-linkedin URLs before calling
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
- Sales Navigator recipient urn must be urn:li:fs_salesProfile
- Sales Navigator lead URL must contain resolved profileId, au
- --limit must be an integer between ${MIN_LIMIT} and ${MAX_LI
- job-url must be a https://www.linkedin.com/jobs/view/<id> UR
- Sales Navigator messaging threads API returned malformed pay
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/aa52b34430656d1e.
Report an issue: GitHub.