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
- Reload the thread page and rerun the command so discovery captures fresh, well-formed resource entries.
- Disable browser extensions that modify network requests or resource timing, then retry.
- 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
- Run in a clean browser profile without network-rewriting extensions.
- Reload the page before capture so performance entries are fresh.
- Never manually construct or edit the discovered URLs — let the discovery script harvest them.
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
- LinkedIn messengerMessages discovery returned an unsafe or m
- google images returned a result row without stable external
- LinkedIn company URL must point to linkedin.com
- LinkedIn company URL must look like /company/<name>
- LinkedIn company URL has a malformed company slug: ${m[1]}
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/44371fa15035b7e8.
Report an issue: GitHub.