jackwener/OpenCLI · error · EmptyResultError
No Sales Navigator thread matched ${input}
Error message
No Sales Navigator thread matched ${input} What it means
When the input is non-empty but not a literal thread id, resolveThreadId paginates up to 500 inbox rows (maxPages pages) and looks for a row matching the parsed recipient/lead/name. If no inbox row matches, it throws EmptyResultError('linkedin salesnav-thread', ...). It signals 'input is valid, but the matcher found nothing in the accessible inbox'.
Source
Thrown at clis/linkedin/salesnav-thread.js:143
return (row.participants || []).some((p) => normalizeWhitespace(p.entity_urn) === criterion);
}
if (kind === 'name') {
const needle = normalizeWhitespace(criterion).toLowerCase();
if (!needle) return false;
if (normalizeWhitespace(row.person_name).toLowerCase() === needle) return true;
return (row.participants || []).some((p) => normalizeWhitespace(p.name).toLowerCase() === needle);
}
return false;
}
async function resolveThreadId(page, input, { maxPages = 30 } = {}) {
const parsed = parseThreadInput(input);
if (parsed[0] === 'empty') throw new ArgumentError('thread or recipient is required');
if (parsed[0] === 'thread_id') return parsed[1];
const inboxRows = await fetchInboxRows(page, { limit: 500, maxPages });
const match = inboxRows.find((row) => threadMatchesInput(row, parsed));
if (!match) {
throw new EmptyResultError('linkedin salesnav-thread', `No Sales Navigator thread matched ${input}`);
}
return match.thread_id;
}
async function fetchThreadWithPagination(page, csrf, threadId, limit = DEFAULT_MESSAGE_LIMIT) {
let requested = THREAD_PAGE_SIZE;
if (limit < requested) requested = limit;
let thread = null;
for (let attempts = 0; attempts < 30; attempts += 1) {
thread = await fetchSalesnavJson(page, csrf, threadApiUrl(threadId, requested), 'Sales Navigator messaging thread API');
const total = Number(thread?.totalMessageCount || 0);
const have = Array.isArray(thread?.messages) ? thread.messages.length : 0;
if (have >= limit || (total && have >= total) || requested >= limit) break;
let nextRequested = requested + THREAD_PAGE_SIZE;
if (total && total > nextRequested) nextRequested = total;
if (nextRequested > limit) nextRequested = limit;
requested = nextRequested;
}View on GitHub (pinned to 49907e53dc)
Solutions
- Pass the numeric Sales Navigator thread id (from the inbox URL) directly instead of a name so resolution is skipped.
- Verify the exact participant name matches Sales Navigator (copy/paste it).
- Increase --max-pages so more inbox pages are scanned before giving up.
- Confirm you are signed into the LinkedIn account that actually owns the conversation.
- Open the thread in Sales Navigator and pass its inbox URL.
Example fix
// before node cli.js linkedin salesnav-thread "Jane Doe" # fuzzy name miss // after node cli.js linkedin salesnav-thread "Jane Doe" --max-pages 60 # or best: pass the thread id from the inbox URL node cli.js linkedin salesnav-thread "5918503635263671296"
Defensive patterns
Strategy: try-catch
Validate before calling
const exact = /^\d+$/.test(input) || input.includes('/inbox/') || input.startsWith('urn:li:'); Type guard
null
Try / catch
try { thread = await threadId(input) } catch (e) { if (e instanceof EmptyResultError) { /* widen search: raise --max-pages or use exact thread id */ } else throw e; } Prevention
- Pass the numeric thread id from the Sales Navigator inbox URL whenever available.
- Copy participant names exactly from Sales Navigator instead of retyping them.
- Increase --max-pages when the account has a large inbox.
- Confirm the browser session is signed into the account that owns the conversation.
When it happens
Trigger: Calling linkedin salesnav-thread with a participant name spelled differently than in Sales Navigator, a lead URL whose lead has no thread in the signed-in account's inbox, or a recipient URN not present in the first 500 inbox rows (maxPages exhausted).
Common situations: Typo or different display-name casing in the participant name; messaging a lead who has never replied so the thread is not in the default inbox view; the account owns thousands of threads so the target is beyond the 500-row/30-page scan limit; signed into the wrong LinkedIn account.
Understand the failure class
Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.
Related errors
- linkedin salesnav-search
- No messages found for ${threadId}
- No LinkedIn Learning results for "${keywords}"
- linkedin connections
- linkedin inbox
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/81dd4dab742f0604.
Report an issue: GitHub.