jackwener/OpenCLI · error · CommandExecutionError

LinkedIn messaging API returned a conversation without threa

Error message

LinkedIn messaging API returned a conversation without thread id

What it means

While walking included entities, each com.linkedin.messenger.Conversation must expose a backendUrn of the form urn:li:messagingThread:<id>. If stripping the prefix yields an empty threadId, parseConversations throws CommandExecutionError because thread_id is the primary key for every returned row and its messaging URL.

Source

Thrown at clis/linkedin/inbox.js:92

  const participantInfo = (p) => {
    if (!p) return { name: '', kind: '' };
    const pt = p.participantType || {};
    if (pt.organization && pt.organization.name) return { name: norm(pt.organization.name.text), kind: 'organization' };
    if (pt.member) {
      const fn = pt.member.firstName && pt.member.firstName.text;
      const ln = pt.member.lastName && pt.member.lastName.text;
      return { name: norm([fn, ln].filter(Boolean).join(' ')), kind: 'member' };
    }
    if (pt.agent && pt.agent.name) return { name: norm(pt.agent.name.text), kind: 'agent' };
    return { name: '', kind: '' };
  };

  const entries = [];
  for (const conv of included) {
    if (!conv || conv.$type !== 'com.linkedin.messenger.Conversation') continue;
    const threadId = String(conv.backendUrn || '').replace(/^urn:li:messagingThread:/, '');
    if (!threadId) {
      throw new CommandExecutionError('LinkedIn messaging API returned a conversation without thread id');
    }

    const others = [];
    let counterpartyKind = '';
    for (const urn of conv['*conversationParticipants'] || []) {
      const p = byUrn.get(urn);
      if (!p) continue;
      if (mailboxUrn && p.hostIdentityUrn === mailboxUrn) continue; // exclude the inbox owner
      const info = participantInfo(p);
      if (info.name) {
        others.push(info.name);
        if (!counterpartyKind) counterpartyKind = info.kind;
      }
    }

    const msgUrns = (conv.messages && conv.messages['*elements']) || [];
    const lastMsg = byUrn.get(msgUrns[0]);
    let preview = lastMsg && lastMsg.body ? norm(lastMsg.body.text) : '';

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Update the CLI — maintainers may add a skip-rule for URN types that cannot yield a thread id.
  2. Retry after reloading /messaging/; placeholder entities from a partial sync usually disappear.
  3. Locally change the throw to `continue` so conversations without backendUrn are skipped instead of aborting the whole listing.
  4. Capture the offending conversation entity and report it so the URN parsing regex can be widened.

Example fix

// before
if (!threadId) {
  throw new CommandExecutionError('LinkedIn messaging API returned a conversation without thread id');
}
// after
if (!threadId) continue; // skip system/sponsored conversations without a messagingThread URN
Defensive patterns

Strategy: type-guard

Validate before calling

function hasThreadUrn(conv) {
  return conv && conv.$type === 'com.linkedin.messenger.Conversation' &&
    typeof conv.backendUrn === 'string' && conv.backendUrn.startsWith('urn:li:messagingThread:');
}
// filter before parsing: entities.filter(hasThreadUrn)

Type guard

function isParsableConversation(entity) {
  return Boolean(entity && entity.$type === 'com.linkedin.messenger.Conversation' &&
    /^urn:li:messagingThread:.+/.test(String(entity.backendUrn || '')));
}

Try / catch

try {
  const convs = await opencli.linkedin.inbox({ limit: 40 });
} catch (e) {
  if (/conversation without thread id/.test(e.message || '')) {
    console.warn('Inbox contained a conversation with no messagingThread URN; retrying.');
    return opencli.linkedin.inbox({ limit: 40 });
  }
  throw e;
}

Prevention

When it happens

Trigger: A conversation entity in normalized.included has no backendUrn (or one with an unexpected URN namespace), which can occur for special/system conversations, sponsored threads, or after a LinkedIn URN format change.

Common situations: LinkedIn introducing new conversation types (InMail campaigns, support threads) lacking messagingThread backendUrns; URN prefix change from urn:li:messagingThread: to a new namespace; partially synced inbox returning placeholder conversation entities.

Related errors


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