jackwener/OpenCLI · error · CommandExecutionError

LinkedIn messengerMessages payload is missing the included e

Error message

LinkedIn messengerMessages payload is missing the included entity array.

What it means

Thrown by parseThreadPages when the normalized payload lacks an 'included' array. LinkedIn's normalized JSON format stores denormalized entities (messages, participants) in 'included'; without it the library cannot reconstruct message text or participants and refuses to return an empty snapshot.

Source

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

  if (!Array.isArray(pages) || pages.length === 0) {
    throw new CommandExecutionError('LinkedIn messengerMessages API returned no pages.');
  }

  const entities = new Map();
  const apiUrls = [];
  for (const page of pages) {
    if (!page || typeof page !== 'object' || Array.isArray(page) || typeof page.url !== 'string') {
      throw new CommandExecutionError('LinkedIn messengerMessages API returned a malformed page wrapper.');
    }
    const normalized = page.json;
    if (!normalized || typeof normalized !== 'object' || Array.isArray(normalized)) {
      throw new CommandExecutionError('LinkedIn messengerMessages API returned a malformed normalized payload.');
    }
    if (Array.isArray(normalized.errors) && normalized.errors.length > 0) {
      throw new CommandExecutionError('LinkedIn messengerMessages GraphQL returned errors.');
    }
    if (!Array.isArray(normalized.included)) {
      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.');

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Ensure the fetch uses accept: application/vnd.linkedin.normalized+json+2.1 so LinkedIn returns the normalized envelope with 'included'.
  2. Reload the thread page and rerun so discovery replays the exact requests the live app made.
  3. If LinkedIn changed envelope versions, update the accept header and parsing to the new format.

Example fix

// before
headers: { 'csrf-token': csrf, accept: 'application/json' },
// after
headers: { 'csrf-token': csrf, accept: 'application/vnd.linkedin.normalized+json+2.1' },
Defensive patterns

Strategy: type-guard

Validate before calling

if (!Array.isArray(json?.included)) throw new Error('Normalized payload missing included[] — check accept header/format version');

Type guard

function hasIncludedEntities(json) {
  return Array.isArray((json)?.included);
}

Try / catch

try {
  const snapshot = await cli.linkedin.threadSnapshot({ url: threadUrl });
} catch (err) {
  if (err.message.includes('missing the included entity array')) {
    // retry with the normalized+json+2.1 accept header; verify envelope version
  } else throw err;
}

Prevention

When it happens

Trigger: normalized.included is undefined, null, or not an array — e.g. the endpoint returned a different envelope version, a stub/empty GraphQL response with data but no included, or the JSON was produced by a non-normalized API response.

Common situations: LinkedIn changed its normalized+json envelope version; the accept header requested a different format version; the thread was deleted so the server returned an empty envelope; a custom fetch accepted application/json instead of the normalized vendor type.

Understand the failure class

Background: "Missing required field" and "field is required" errors: why libraries reject payloads that omit mandatory fields — this error's family across 20 libraries.

Related errors


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