jackwener/OpenCLI · error · CommandExecutionError

LinkedIn messengerMessages discovery returned an invalid URL

Error message

LinkedIn messengerMessages discovery returned an invalid URL.

What it means

Thrown by validateThreadApiUrls when a captured discovery URL cannot be parsed with the URL constructor. The library defensively validates every URL harvested from the browser's performance entries before replaying it, and an unparseable string means the discovery data is corrupt or was tampered with.

Source

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

    let decoded = url;
    try { decoded = decodeURIComponent(url); } catch {}
    const match = decoded.match(/conversationUrn:urn:li:msg_conversation:\((urn:li:fsd_profile:[^,)]+)/i);
    if (match) return match[1];
  }
  return '';
}

function validateThreadApiUrls(apiUrls, threadUrl) {
  const threadId = new URL(threadUrl).pathname.match(/^\/messaging\/thread\/([^/]+)\/?$/i)?.[1] || '';
  if (!Array.isArray(apiUrls) || apiUrls.length === 0) {
    throw new CommandExecutionError('LinkedIn did not issue a messengerMessages API request for this thread.');
  }
  for (const value of apiUrls) {
    let url;
    try {
      url = new URL(value);
    } catch {
      throw new CommandExecutionError('LinkedIn messengerMessages discovery returned an invalid URL.');
    }
    let decoded = value;
    try { decoded = decodeURIComponent(value); } catch {}
    if (url.protocol !== 'https:'
      || url.hostname !== LINKEDIN_DOMAIN
      || url.pathname !== '/voyager/api/voyagerMessagingGraphQL/graphql'
      || !/^messengerMessages\.[a-f0-9]+$/i.test(url.searchParams.get('queryId') || '')
      || !threadId
      || !decoded.includes(threadId)) {
      throw new CommandExecutionError('LinkedIn messengerMessages discovery returned an unsafe or mismatched URL.');
    }
  }
  return apiUrls;
}

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

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Reload the thread page and rerun the command so discovery captures fresh, well-formed resource entries.
  2. Disable browser extensions that modify network requests or resource timing, then retry.
  3. Inspect the captured values (log apiUrls before validation) and widen/narrow the discovery regex in buildThreadApiDiscoveryScript to match only well-formed URLs.

Example fix

// before: accepting any voyager match
if (!/\/voyager\/api\/voyagerMessagingGraphQL\/graphql/i.test(url)) continue;
// after: require a queryId and parseable shape before pushing
if (!/\/[?&]queryId=messengerMessages\.[a-f0-9]+/i.test(url)) continue;
try { new URL(url); } catch { continue; }
apiUrls.push(url);
Defensive patterns

Strategy: validation

Validate before calling

function validateApiUrls(urls) {
  if (!Array.isArray(urls)) throw new Error('apiUrls must be an array');
  for (const u of urls) new URL(u); // throws TypeError on unparseable
}

Type guard

function isParseableUrl(v) {
  if (typeof v !== 'string') return false;
  try { new URL(v); return true; } catch { return false; }
}

Try / catch

try {
  const snapshot = await cli.linkedin.threadSnapshot({ url: threadUrl });
} catch (err) {
  if (err.message.includes('discovery returned an invalid URL')) {
    // retry once on a freshly reloaded page; else report LinkedIn/extension interference
  } else throw err;
}

Prevention

When it happens

Trigger: An entry in performance resource entries matched the voyager GraphQL regex but produced a string that new URL(value) rejects (malformed, empty after trimming, or containing invalid characters).

Common situations: A browser extension or injected script polluted resource timing entries; LinkedIn served a redirect/proxy URL with unencoded characters; truncated URLs from a modified performance buffer; custom instrumentation recording partial URLs.

Related errors


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