jackwener/OpenCLI · error · CommandExecutionError

Sales Navigator messaging threads API returned malformed pay

Error message

Sales Navigator messaging threads API returned malformed payload

What it means

This CommandExecutionError is thrown by parseSalesnavThreads when the Sales Navigator messaging threads API response is not an object with an elements array. It guards against HTML error pages, auth redirects, or schema changes reaching the row parser.

Source

Thrown at clis/linkedin/salesnav-inbox.js:61

  const resolution = thread?.participantsResolutionResults || {};
  const participants = Array.isArray(thread?.participants) ? thread.participants : Object.keys(resolution);
  return participants.map((urn) => resolution[urn] || { entityUrn: urn }).filter(Boolean);
}

function isSelfParticipant(profile) {
  const degree = String(profile?.degree ?? '').trim();
  return degree === '0';
}

function otherParticipantName(thread) {
  const participants = getThreadParticipants(thread);
  const other = participants.find((p) => !isSelfParticipant(p)) || participants[0];
  return normalizeWhitespace(other?.fullName || [other?.firstName, other?.lastName].filter(Boolean).join(' '));
}

function parseSalesnavThreads(json) {
  if (!json || typeof json !== 'object' || !Array.isArray(json.elements)) {
    throw new CommandExecutionError('Sales Navigator messaging threads API returned malformed payload');
  }
  return json.elements.map((thread) => {
    if (!thread || typeof thread !== 'object') {
      throw new CommandExecutionError('Sales Navigator messaging threads API returned malformed thread row');
    }
    const messages = Array.isArray(thread?.messages) ? thread.messages : [];
    const lastMessage = messages[0] || {};
    const deliveredAt = Number(lastMessage.deliveredAt || thread?.nextPageStartsAt || 0);
    const threadId = normalizeWhitespace(thread?.id || '');
    if (!threadId) {
      throw new CommandExecutionError('Sales Navigator messaging thread row missing id');
    }
    return {
      thread_id: threadId,
      thread_url: salesnavThreadUrl(threadId),
      person_name: otherParticipantName(thread),
      last_message_snippet: normalizeWhitespace(lastMessage.body || lastMessage.subject || '').slice(0, 300),
      last_activity_time: deliveredAt ? new Date(deliveredAt).toISOString() : '',

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Re-authenticate / refresh the LinkedIn session and retry
  2. Verify the CSRF token is fresh (getCsrf) before calling the API
  3. Update the library if Sales Navigator changed the threads response schema
  4. Log the raw response body to confirm what the endpoint actually returned

Example fix

// before
const json = JSON.parse(rawText);
parseSalesnavThreads(json);
// after
const json = JSON.parse(rawText);
if (!json?.elements) throw new Error('threads payload missing elements: ' + rawText.slice(0, 200));
parseSalesnavThreads(json);
Defensive patterns

Strategy: validation

Validate before calling

const json = await fetchPageJson(url);
if (!json || typeof json !== 'object' || !Array.isArray(json.elements)) {
  throw new Error('Threads payload malformed; raw: ' + JSON.stringify(json).slice(0, 200));
}

Type guard

function isThreadsPayload(v) {
  return !!v && typeof v === 'object' && Array.isArray(v.elements);
}

Try / catch

try {
  const rows = await fetchInboxRows(page);
} catch (e) {
  if (String(e.message).includes('malformed payload')) {
    await relogin(page); // often a stale session
    return fetchInboxRows(page);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling fetchInboxRows/pageRows when the Sales Nav messaging endpoint returns JSON lacking json.elements — e.g. a login redirect body, a rate-limit JSON error, or a LinkedIn API schema change renaming/moving elements.

Common situations: Expired Sales Navigator session returning a non-thread payload; CSRF token stale so the API answers with an error envelope; LinkedIn changed the messaging threads response shape; hitting the wrong endpoint URL.

Understand the failure class

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/9463da333612f2d7. Report an issue: GitHub.