jackwener/OpenCLI · error · CommandExecutionError

LinkedIn messengerMessages payload contains a message withou

Error message

LinkedIn messengerMessages payload contains a message without an id.

What it means

For every com.linkedin.messenger.Message entity, parseThreadPages derives an id from entityUrn || backendUrn || originToken. It throws when all three are empty/whitespace, because messages must be keyed by a stable id for deduplication and sorting.

Source

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

  }

  const participants = Array.from(entities.values()).filter(
    (entity) => entity.$type === 'com.linkedin.messenger.MessagingParticipant',
  );
  const recipientNames = Array.from(new Set(participants
    .filter((participant) => participant.hostIdentityUrn !== ownerUrn)
    .map(participantName)
    .filter(Boolean)));
  if (recipientNames.length === 0) {
    throw new CommandExecutionError('LinkedIn messengerMessages payload is missing the counterparty participant.');
  }

  const byMessageId = new Map();
  for (const entity of entities.values()) {
    if (entity.$type !== 'com.linkedin.messenger.Message') continue;
    const messageId = normalizeWhitespace(entity.entityUrn || entity.backendUrn || entity.originToken);
    if (!messageId) {
      throw new CommandExecutionError('LinkedIn messengerMessages payload contains a message without an id.');
    }
    const deliveredAt = Number(entity.deliveredAt);
    if (!Number.isFinite(deliveredAt) || deliveredAt <= 0) {
      throw new CommandExecutionError('LinkedIn messengerMessages payload contains a message without a valid timestamp.');
    }
    const senderUrn = normalizeWhitespace(entity['*sender'] || entity['*actor']);
    const sender = senderUrn ? entities.get(senderUrn) : null;
    const speaker = participantName(sender);
    if (!speaker) {
      throw new CommandExecutionError('LinkedIn messengerMessages payload contains a message with an unresolved sender.');
    }
    byMessageId.set(messageId, {
      messageUrn: messageId,
      speaker,
      text: messageText(entity),
      deliveredAt,
    });
  }

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Update the library to match the current Message entity id field names
  2. Re-capture the thread — partial hydration is often transient
  3. Log and inspect the offending entity's keys to find the new id field, and extend the fallback chain
  4. If building fixtures, ensure every Message entity carries at least one of entityUrn/backendUrn/originToken

Example fix

// before
const messageId = normalizeWhitespace(entity.entityUrn || entity.backendUrn || entity.originToken);
// after: extend fallback to new schema field
const messageId = normalizeWhitespace(entity.entityUrn || entity.backendUrn || entity.originToken || entity.messageUrn);
Defensive patterns

Strategy: type-guard

Validate before calling

function messageHasId(entity) {
  return !!(entity.entityUrn || entity.backendUrn || entity.originToken);
}
const bad = payloads.flatMap(p => p.included).filter(e => e?.$type === 'com.linkedin.messenger.Message' && !messageHasId(e));
if (bad.length) throw new Error('Message entities missing ids: ' + bad.length);

Type guard

const hasMessageId = (e) => typeof (e.entityUrn || e.backendUrn || e.originToken) === 'string' && !!(e.entityUrn || e.backendUrn || e.originToken).trim();

Try / catch

try {
  const snap = await run('linkedin thread-snapshot', { 'thread-url': url });
} catch (err) {
  if (String(err.message).includes('message without an id')) {
    // schema drift: log entity keys and upgrade parser
  } else throw err;
}

Prevention

When it happens

Trigger: A Message entity in `included` has none of entityUrn, backendUrn, or originToken set — e.g. LinkedIn schema change renaming the id field, or a partially hydrated entity from a truncated page.

Common situations: Outdated parser after a LinkedIn GraphQL schema update; stub/placeholder entities returned in some response variants; manually recorded fixtures missing id fields.

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/7766971b69ff7a11. Report an issue: GitHub.