{"record":{"id":"4a879e0e4e75301e","repo":"jackwener/OpenCLI","slug":"no-messages-found-for-threadid","errorCode":null,"errorMessage":"No messages found for ${threadId}","messagePattern":"No messages found for (.+?)","errorType":"exception","errorClass":"EmptyResultError","httpStatus":null,"severity":"warning","filePath":"clis/linkedin/salesnav-thread.js","lineNumber":196,"sourceCode":"  args: [\n    { 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' },\n    { name: 'limit', type: 'number', default: DEFAULT_MESSAGE_LIMIT, help: 'Maximum messages to return (1-500)' },\n    { name: 'max-pages', type: 'number', default: 30, help: 'Maximum inbox pages to scan when resolving a recipient' },\n  ],\n  columns: ['index', 'thread_id', 'thread_url', 'sender', 'text', 'timestamp', 'subject', 'message_id', 'sender_urn', 'delivered_at', 'type', 'total_message_count'],\n  func: async (page, args) => {\n    if (!page) throw new CommandExecutionError('Browser session required for linkedin salesnav-thread');\n    const input = normalizeWhitespace(args['thread-or-recipient']);\n    if (!input) throw new ArgumentError('thread-or-recipient is required');\n    const limit = parseLimit(args.limit, DEFAULT_MESSAGE_LIMIT);\n    const maxPages = parseLimit(args['max-pages'], 30);\n    await page.goto(SALES_INBOX_URL);\n    await page.wait(4);\n    const threadId = await resolveThreadId(page, input, { maxPages });\n    const csrf = await getCsrf(page);\n    const thread = await fetchThreadWithPagination(page, csrf, threadId, limit);\n    const messages = parseSalesnavThreadMessages(thread).slice(0, limit);\n    if (messages.length === 0) throw new EmptyResultError('linkedin salesnav-thread', `No messages found for ${threadId}`);\n    return messages.map((message) => ({\n      ...message,\n      thread_url: salesnavThreadUrl(threadId),\n      total_message_count: Number(thread?.totalMessageCount || messages.length),\n    }));\n  },\n});\n\nexport const __test__ = {\n  parseThreadInput,\n  threadApiUrl,\n  participantIndex,\n  parseSalesnavThreadMessages,\n  threadMatchesInput,\n  salesnavThreadUrl,\n};\n","sourceCodeStart":178,"sourceCodeEnd":213,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/linkedin/salesnav-thread.js#L178-L213","documentation":"After resolving the thread and fetching it, the command parses messages and slices to the limit; if the parsed list is empty it throws EmptyResultError('linkedin salesnav-thread', `No messages found for ${threadId}`). It fires when the thread object yielded no parseable messages even though a thread id was resolved.","triggerScenarios":"The thread API returned a thread whose messages array is empty or in an unexpected shape (e.g. new message types or schema change the parser doesn't recognize), or a brand-new/empty thread was passed.","commonSituations":"Pointing at a thread with zero retrievable messages; LinkedIn messaging API response shape changed so parseSalesnavThreadMessages returns []; transient empty API response on the first fetch; passing a stale/deleted thread id that still resolves.","solutions":["Retry the command once to rule out a transient empty API response.","Open the thread in Sales Navigator to confirm it actually has messages.","Inspect the raw thread API response and update parseSalesnavThreadMessages if LinkedIn changed the message schema.","Use a different, known-good thread id to isolate whether the parser or the thread is at fault."],"exampleFix":"// before\nconst messages = parseSalesnavThreadMessages(thread)   // [] on schema drift\n// after\nconst messages = parseSalesnavThreadMessages(thread)\nif (messages.length === 0 && Array.isArray(thread?.messages) && thread.messages.length > 0) {\n  console.warn('parser produced 0 messages from non-empty thread; check schema')\n}","handlingStrategy":"try-catch","validationCode":"null","typeGuard":"function hasMessages(t){ return Array.isArray(t?.messages) && t.messages.length > 0; }","tryCatchPattern":"try { msgs = await fetch() } catch (e) { if (e instanceof EmptyResultError && /No messages found/.test(e.message)) { msgs = []; /* return empty result set deliberately */ } else throw e; }","preventionTips":["Verify the thread has visible messages in Sales Navigator before automation.","Retry once to rule out transient empty responses.","Keep the parser in sync with the LinkedIn thread API schema.","Log the raw thread payload when this error occurs to detect schema drift."],"tags":["empty-result","parser","linkedin","sales-navigator"],"backgroundTag":"empty-result-set","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}