{"record":{"id":"3572c2e23f938900","repo":"jackwener/OpenCLI","slug":"linkedin-messengermessages-api-authentication-fail","errorCode":null,"errorMessage":"LinkedIn messengerMessages API authentication failed: ${fetched.error}","messagePattern":"LinkedIn messengerMessages API authentication failed: (.+?)","errorType":"exception","errorClass":"AuthRequiredError","httpStatus":null,"severity":"error","filePath":"clis/linkedin/thread-snapshot.js","lineNumber":356,"sourceCode":"    if (!discovery || typeof discovery !== 'object' || Array.isArray(discovery) || !Array.isArray(discovery.apiUrls)) {\n      throw new CommandExecutionError('LinkedIn thread-snapshot returned a malformed API discovery payload.');\n    }\n\n    const actualUrl = canonicalizeLinkedInThreadUrl(discovery.url || '');\n    if (threadUrl && actualUrl && threadUrl !== actualUrl) {\n      throw new CommandExecutionError('LinkedIn thread-snapshot blocked: thread_url_mismatch', `Expected ${threadUrl}; actual ${actualUrl}`);\n    }\n    if (maxScrolls >= 4 && discovery.scrollAttempts >= maxScrolls && discovery.scrollStable === false) {\n      throw new CommandExecutionError('LinkedIn thread history did not stabilize before --max-scrolls; refusing to return a partial snapshot.');\n    }\n\n    const apiUrls = validateThreadApiUrls(discovery.apiUrls, threadUrl);\n    const csrf = await requireLinkedInCookie(page, 'LinkedIn thread-snapshot');\n    const fetched = unwrapEvaluateResult(\n      await page.evaluate(buildFetchThreadPagesScript(apiUrls, csrf)),\n    );\n    if (fetched?.authRequired) {\n      throw new AuthRequiredError(LINKEDIN_DOMAIN, `LinkedIn messengerMessages API authentication failed: ${fetched.error}`);\n    }\n    if (!fetched || fetched.error || !Array.isArray(fetched.pages)) {\n      throw new CommandExecutionError(`LinkedIn messengerMessages API returned an unexpected response: ${fetched?.error || 'no data'}`);\n    }\n\n    const parsed = parseThreadPages(fetched.pages);\n    const recipient = parsed.recipientNames.join(', ');\n    const latestMessageText = parsed.messages[parsed.messages.length - 1]?.text || '';\n    const normalized = {\n      url: actualUrl || threadUrl,\n      title: normalizeWhitespace(discovery.title),\n      headerNames: parsed.recipientNames,\n      latestMessageText,\n      messages: parsed.messages,\n      messageCount: parsed.messages.length,\n      authRequired: false,\n      extractedAt: new Date().toISOString(),\n      maxScrolls,","sourceCodeStart":338,"sourceCodeEnd":374,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/linkedin/thread-snapshot.js#L338-L374","documentation":"After discovering the thread's messengerMessages API URLs, thread-snapshot fetches them in-page with the session CSRF token. If the fetch reports authRequired — LinkedIn returned a login wall or 401/403-style error — the command throws AuthRequiredError, meaning the browser session is no longer signed in for API calls.","triggerScenarios":"The signed-in session cookie/CSRF token expired between page load and the API fetch; LinkedIn invalidated the session (logged out elsewhere, security challenge); fetch to messengerMessages returns a redirect to the login page.","commonSituations":"Long-running browser sessions where LinkedIn expires the session; logging into LinkedIn from another device; triggering LinkedIn's bot/security challenge; corporate network proxying interfering with session cookies.","solutions":["Re-authenticate in the linked browser: run the site auth/login flow for linkedin.com and retry","Verify the LinkedIn home feed renders as signed-in before re-running thread-snapshot","Clear stale LinkedIn cookies and log in fresh if the session is in a half-valid state","Check for a security challenge/verification email from LinkedIn blocking the session"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"const cookies = await page.getCookies({ url: 'https://www.linkedin.com' });\nconst signedIn = cookies.some(c => c.name === 'li_at' && c.value);\nif (!signedIn) throw new Error('Run the LinkedIn login flow first');","typeGuard":"const hasLinkedInSession = (cookies) => Array.isArray(cookies) && cookies.some(c => c.name === 'li_at' && c.value);","tryCatchPattern":"try {\n  await threadSnapshot({ threadUrl });\n} catch (e) {\n  if (e.name === 'AuthRequiredError' || String(e.message).includes('authentication failed')) {\n    await linkedinLogin(); // re-authenticate then retry\n  } else throw e;\n}","preventionTips":["Use a persistent browser profile so li_at survives restarts","Re-login before long automation runs","Watch for LinkedIn security-challenge emails","Avoid logging into LinkedIn from many devices simultaneously"],"tags":["linkedin","authentication","session-expired","browser-automation"],"backgroundTag":"auth-session-expired","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}