jackwener/OpenCLI · error · CommandExecutionError

LinkedIn messengerMessages payload contains a malformed incl

Error message

LinkedIn messengerMessages payload contains a malformed included entity.

What it means

parseThreadPages validates every entry of the LinkedIn messengerMessages GraphQL `included` array. The library throws this error when any element of `included` is null, not an object, or an array, because entity extraction relies on reading per-entity fields like entityUrn and $type. A malformed element means LinkedIn's payload shape changed or was corrupted, and proceeding could silently drop or misattribute message data.

Source

Thrown at clis/linkedin/thread-snapshot.js:236

      throw new CommandExecutionError('LinkedIn messengerMessages payload is missing the included entity array.');
    }
    const data = normalized.data?.data;
    if (!data || typeof data !== 'object' || Array.isArray(data)) {
      throw new CommandExecutionError('LinkedIn messengerMessages payload is missing normalized data.');
    }
    const container = Object.entries(data).find(([key, value]) => (
      /^messengerMessages/i.test(key)
      && value
      && typeof value === 'object'
      && !Array.isArray(value)
      && (Array.isArray(value['*elements']) || Array.isArray(value.elements))
    ));
    if (!container) {
      throw new CommandExecutionError('LinkedIn messengerMessages payload is missing a message collection.');
    }
    for (const entity of normalized.included) {
      if (!entity || typeof entity !== 'object' || Array.isArray(entity)) {
        throw new CommandExecutionError('LinkedIn messengerMessages payload contains a malformed included entity.');
      }
      if (entity.entityUrn) {
        const existing = entities.get(entity.entityUrn);
        if (!existing || Object.keys(entity).length > Object.keys(existing).length) {
          entities.set(entity.entityUrn, entity);
        }
      }
    }
    apiUrls.push(page.url);
  }

  const ownerUrn = ownerUrnFromApiUrls(apiUrls);
  if (!ownerUrn) {
    throw new CommandExecutionError('LinkedIn messengerMessages URL is missing the conversation owner identity.');
  }

  const participants = Array.from(entities.values()).filter(
    (entity) => entity.$type === 'com.linkedin.messenger.MessagingParticipant',

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Update the CLI/library to the latest version so parsers match LinkedIn's current messengerMessages schema
  2. Re-capture the thread (re-run the command) — transient truncation or injected error pages often resolve on retry
  3. Inspect the captured response payload and confirm `included` contains only entity objects; if scraping yourself, sanitize entries before parsing
  4. If using a proxy, disable response rewriting/HTML injection for voyager API calls

Example fix

// before: pages captured by an older scraper with array-shaped included entries
const normalized = page.json; // included: [ ['urn:li:msg:1'], {...} ]
// after: upgrade the capture script / re-record pages so each included entry is an entity object
const normalized = page.json; // included: [ { entityUrn: 'urn:li:msg:1', $type: '...' }, {...} ]
Defensive patterns

Strategy: validation

Validate before calling

function isValidIncluded(payload) {
  return !!payload && Array.isArray(payload.included)
    && payload.included.every(e => e && typeof e === 'object' && !Array.isArray(e));
}
if (!pages.every(p => p?.json && isValidIncluded(p.json))) throw new Error('Malformed included entities before calling CLI');

Type guard

const isEntity = (e) => !!e && typeof e === 'object' && !Array.isArray(e);

Try / catch

try {
  await run('linkedin thread-snapshot', { 'thread-url': url });
} catch (err) {
  if (String(err.message).includes('malformed included entity')) {
    // payload shape drift: re-capture or upgrade library
  } else throw err;
}

Prevention

When it happens

Trigger: A captured messengerMessages page has an `included` array containing null, a primitive, or a nested array element instead of entity objects — typically after LinkedIn changes its Voyager GraphQL response format or a truncated/proxied response.

Common situations: Running with an outdated CLI against a new LinkedIn API schema; using HTTP mocks/fixtures recorded from a different API version; middleman proxies or HTML error pages injected into a captured network response.

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.

Related errors


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