{"record":{"id":"4707911728cac9e7","repo":"jackwener/OpenCLI","slug":"linkedin-messengermessages-payload-is-missing-the-470791","errorCode":null,"errorMessage":"LinkedIn messengerMessages payload is missing the counterparty participant.","messagePattern":"LinkedIn messengerMessages payload is missing the counterparty participant\\.","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/linkedin/thread-snapshot.js","lineNumber":261,"sourceCode":"      }\n    }\n    apiUrls.push(page.url);\n  }\n\n  const ownerUrn = ownerUrnFromApiUrls(apiUrls);\n  if (!ownerUrn) {\n    throw new CommandExecutionError('LinkedIn messengerMessages URL is missing the conversation owner identity.');\n  }\n\n  const participants = Array.from(entities.values()).filter(\n    (entity) => entity.$type === 'com.linkedin.messenger.MessagingParticipant',\n  );\n  const recipientNames = Array.from(new Set(participants\n    .filter((participant) => participant.hostIdentityUrn !== ownerUrn)\n    .map(participantName)\n    .filter(Boolean)));\n  if (recipientNames.length === 0) {\n    throw new CommandExecutionError('LinkedIn messengerMessages payload is missing the counterparty participant.');\n  }\n\n  const byMessageId = new Map();\n  for (const entity of entities.values()) {\n    if (entity.$type !== 'com.linkedin.messenger.Message') continue;\n    const messageId = normalizeWhitespace(entity.entityUrn || entity.backendUrn || entity.originToken);\n    if (!messageId) {\n      throw new CommandExecutionError('LinkedIn messengerMessages payload contains a message without an id.');\n    }\n    const deliveredAt = Number(entity.deliveredAt);\n    if (!Number.isFinite(deliveredAt) || deliveredAt <= 0) {\n      throw new CommandExecutionError('LinkedIn messengerMessages payload contains a message without a valid timestamp.');\n    }\n    const senderUrn = normalizeWhitespace(entity['*sender'] || entity['*actor']);\n    const sender = senderUrn ? entities.get(senderUrn) : null;\n    const speaker = participantName(sender);\n    if (!speaker) {\n      throw new CommandExecutionError('LinkedIn messengerMessages payload contains a message with an unresolved sender.');","sourceCodeStart":243,"sourceCodeEnd":279,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/linkedin/thread-snapshot.js#L243-L279","documentation":"parseThreadPages filters MessagingParticipant entities to those whose hostIdentityUrn differs from the owner URN, then derives display names. It throws when no counterparty (non-owner) participant yields a name, meaning the payload has no usable other-side participant entity — so the snapshot would have no 'recipient'.","triggerScenarios":"All MessagingParticipant entities match the owner URN, participantName() returns empty for the counterparty entities, or the counterparty participant entity is absent from `included` (e.g. restricted/deactivated profile or incomplete included array).","commonSituations":"Messaging a restricted or deleted account; LinkedIn omitting participant entities for privacy; a truncated page capture that missed participant entities; self-directed threads (message to self) that genuinely have no counterparty.","solutions":["Re-run the snapshot to capture a complete payload including participant entities","Update the library — participantName may need to handle new name field layouts for MessagingParticipant","Test with a normal thread with an active counterparty to confirm the tool works; threads to self/deactivated accounts are unsupported","If capturing manually, include all pages so participant entities in later pages aren't lost"],"exampleFix":"// before: participant entity lacking name fields\n{ \"$type\": \"com.linkedin.messenger.MessagingParticipant\", \"hostIdentityUrn\": \"urn:li:person:abc\" }\n// after: complete capture including the linked miniProfile name fields\n{ \"$type\": \"com.linkedin.messenger.MessagingParticipant\", \"hostIdentityUrn\": \"urn:li:person:abc\", \"name\": { \"firstName\": \"Jane\", \"lastName\": \"Doe\" } }","handlingStrategy":"validation","validationCode":"function hasCounterparty(payload, ownerUrn) {\n  return payload.included.some(e => e?.$type === 'com.linkedin.messenger.MessagingParticipant'\n    && e.hostIdentityUrn !== ownerUrn);\n}\nif (!pages.every(p => hasCounterparty(p.json, myOwnerUrn))) throw new Error('No counterparty participant captured');","typeGuard":"const isParticipant = (e) => !!e && typeof e === 'object' && e.$type === 'com.linkedin.messenger.MessagingParticipant' && typeof e.hostIdentityUrn === 'string';","tryCatchPattern":"try {\n  const snap = await run('linkedin thread-snapshot', { 'thread-url': url });\n} catch (err) {\n  if (String(err.message).includes('missing the counterparty participant')) {\n    // handle self-threads or restricted profiles gracefully\n  } else throw err;\n}","preventionTips":["Skip threads with no active counterparty (self-messages, deactivated accounts)","Capture all pages so participant entities aren't dropped","Keep participantName parsing updated for name field layout changes"],"tags":["linkedin","participant-missing","payload-validation"],"backgroundTag":"missing-required-field","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}