jackwener/OpenCLI · error · CommandExecutionError
Sales Navigator messaging thread API returned malformed mess
Error message
Sales Navigator messaging thread API returned malformed messages
What it means
Thrown by parseSalesnavThreadMessages (clis/linkedin/salesnav-thread.js:94) when thread.messages is present but not an array. The parser requires an array to map each message into an output row. This indicates the API payload deviates from the expected decoration shape, typically because the response came from a different endpoint/version or was partially decoded.
Source
Thrown at clis/linkedin/salesnav-thread.js:94
const participants = Array.isArray(thread?.participants) ? thread.participants : Object.keys(resolution);
const byUrn = new Map();
for (const urn of participants) {
const profile = resolution[urn] || { entityUrn: urn };
byUrn.set(urn, profile);
}
return byUrn;
}
function parseSalesnavThreadMessages(thread) {
if (!thread || typeof thread !== 'object') {
throw new CommandExecutionError('Sales Navigator messaging thread API returned malformed payload');
}
const threadId = normalizeWhitespace(thread?.id || '');
if (!threadId) {
throw new CommandExecutionError('Sales Navigator messaging thread API returned a thread without id');
}
if (!Array.isArray(thread?.messages)) {
throw new CommandExecutionError('Sales Navigator messaging thread API returned malformed messages');
}
const byUrn = participantIndex(thread);
const messages = thread.messages;
const rows = messages.map((message) => {
if (!message || typeof message !== 'object') {
throw new CommandExecutionError('Sales Navigator messaging thread API returned malformed message row');
}
const deliveredAt = Number(message?.deliveredAt || 0);
const senderProfile = byUrn.get(message?.author);
return {
message_id: normalizeWhitespace(message?.id || ''),
thread_id: threadId,
sender: participantName(senderProfile) || normalizeWhitespace(message?.author || ''),
sender_urn: normalizeWhitespace(message?.author || ''),
text: normalizeWhitespace(message?.body || message?.systemMessageContent || ''),
subject: normalizeWhitespace(message?.subject || ''),
timestamp: deliveredAt ? new Date(deliveredAt).toISOString() : '',
delivered_at: deliveredAt || '',View on GitHub (pinned to 49907e53dc)
Solutions
- Re-run the command; if it recurs, the payload shape has changed rather than being transient.
- Inspect the raw response (log Object.keys(thread) and typeof thread.messages) to find where messages now live under the current decoration.
- Update THREAD_DECORATION from a live /sales-api/salesApiThreads network capture so the decoder restores the messages array.
- Confirm you parsed the thread-detail endpoint response; inbox-list rows keep messages elsewhere and will fail this check.
Example fix
// before
const rows = parseSalesnavThreadMessages(thread);
// after (tolerate missing messages for empty threads)
const safeThread = { ...thread, messages: Array.isArray(thread.messages) ? thread.messages : [] };
const rows = parseSalesnavThreadMessages(safeThread); Defensive patterns
Strategy: type-guard
Validate before calling
// Coerce/guard messages before parsing:
const safeThread = { ...thread, messages: Array.isArray(thread.messages) ? thread.messages : [] };
// note: an empty array still means 'no messages', which the caller should expect Type guard
function hasMessagesArray(t) {
return t !== null && typeof t === 'object' && Array.isArray(t.messages);
} Try / catch
try {
const messages = parseSalesnavThreadMessages(thread);
} catch (err) {
if (/malformed messages/.test(err.message)) {
console.error('messages is not an array — check decoration version and raw payload keys:', Object.keys(thread || {}));
throw err;
}
throw err;
} Prevention
- Log Object.keys(thread) and typeof thread.messages whenever this error occurs to detect decoration drift early.
- Confirm messageCount handling: zero-message threads may omit the field; normalize to [] upstream if that outcome is valid.
- Refresh THREAD_DECORATION from a live capture after any Sales Navigator behavior change.
When it happens
Trigger: The decoration version mismatch relocates messages into a nested object or renames the field (e.g. messagesResolutionResults); fetchSalesnavJson returned an error/HTML-parsed object where messages is a string; caller passes a thread summary object that omits messages entirely (undefined fails the Array.isArray check).
Common situations: LinkedIn Sales Navigator redeploys changing the message container; calling the parser with a thread object built from the wrong endpoint; messageCount=0 edge responses where the field is omitted rather than returned as [].
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Sales Navigator messaging thread API returned malformed payl
- Sales Navigator messaging thread API returned a thread witho
- Sales Navigator messaging thread API returned malformed mess
- Sales Navigator lead search API returned malformed payload
- Sales Navigator lead search API returned malformed lead row
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/653808ae73961e8b.
Report an issue: GitHub.