jackwener/OpenCLI · error · ArgumentError
thread-or-recipient is required
Error message
thread-or-recipient is required
What it means
The command's func normalizes the positional 'thread-or-recipient' argument with normalizeWhitespace; if the result is an empty string it throws ArgumentError('thread-or-recipient is required'). This is the top-level argument check and mirrors the deeper resolveThreadId 'empty' guard (error 2400) but fires before any page navigation.
Source
Thrown at clis/linkedin/salesnav-thread.js:187
cli({
site: 'linkedin',
name: 'salesnav-thread',
access: 'read',
description: 'Return full Sales Navigator message history for a thread id, Sales Navigator inbox URL, lead URL, recipient urn, or exact recipient name',
domain: LINKEDIN_DOMAIN,
strategy: Strategy.UI,
browser: true,
args: [
{ name: 'thread-or-recipient', type: 'string', required: true, positional: true, help: 'Sales Navigator inbox URL/thread id, Sales Navigator lead URL, recipient urn, or exact participant name' },
{ name: 'limit', type: 'number', default: DEFAULT_MESSAGE_LIMIT, help: 'Maximum messages to return (1-500)' },
{ name: 'max-pages', type: 'number', default: 30, help: 'Maximum inbox pages to scan when resolving a recipient' },
],
columns: ['index', 'thread_id', 'thread_url', 'sender', 'text', 'timestamp', 'subject', 'message_id', 'sender_urn', 'delivered_at', 'type', 'total_message_count'],
func: async (page, args) => {
if (!page) throw new CommandExecutionError('Browser session required for linkedin salesnav-thread');
const input = normalizeWhitespace(args['thread-or-recipient']);
if (!input) throw new ArgumentError('thread-or-recipient is required');
const limit = parseLimit(args.limit, DEFAULT_MESSAGE_LIMIT);
const maxPages = parseLimit(args['max-pages'], 30);
await page.goto(SALES_INBOX_URL);
await page.wait(4);
const threadId = await resolveThreadId(page, input, { maxPages });
const csrf = await getCsrf(page);
const thread = await fetchThreadWithPagination(page, csrf, threadId, limit);
const messages = parseSalesnavThreadMessages(thread).slice(0, limit);
if (messages.length === 0) throw new EmptyResultError('linkedin salesnav-thread', `No messages found for ${threadId}`);
return messages.map((message) => ({
...message,
thread_url: salesnavThreadUrl(threadId),
total_message_count: Number(thread?.totalMessageCount || messages.length),
}));
},
});
export const __test__ = {View on GitHub (pinned to 49907e53dc)
Solutions
- Provide the positional thread-or-recipient value (inbox URL, thread id, lead URL, recipient URN, or participant name).
- Trim the value; whitespace-only input is rejected.
- Guard calling scripts so they abort when the value is empty.
- Use the CLI's --help to confirm the positional arity.
Example fix
// before node cli.js linkedin salesnav-thread # missing positional // after node cli.js linkedin salesnav-thread "https://www.linkedin.com/sales/inbox/5918503635263671296"
Defensive patterns
Strategy: validation
Validate before calling
const v = (args['thread-or-recipient'] ?? '').trim(); if (!v) throw new Error('usage: linkedin salesnav-thread <inbox-url|thread-id|lead-url|urn|name>'); Type guard
function isNonEmptyString(v){ return typeof v === 'string' && v.trim().length > 0; } Try / catch
try { await cli() } catch (e) { if (e instanceof ArgumentError && e.message === 'thread-or-recipient is required') { process.exitCode = 2; console.error(e.message); } else throw e; } Prevention
- Quote the positional argument in shell scripts so it is never dropped.
- Guard interpolated variables for emptiness before invocation.
- Document the positional in wrapper scripts and validate there first.
- Use --help to confirm argument arity before scripting.
When it happens
Trigger: Invoking linkedin salesnav-thread with no positional argument, an empty string, or a whitespace-only string.
Common situations: Forgetting the positional argument on the command line; a build script interpolating an empty variable; quoting mistakes so the shell drops the argument; passing args as named flags instead of the required positional.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- coingecko derivatives limit must be a positive integer
- --from and --to must differ (got ${fromCity})
- ${label} must be a positive integer
- ${label} must be an integer >= ${min}
- Invalid HN item id: ${args.id}
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/b2fb4f6ce506c86e.
Report an issue: GitHub.