{"record":{"id":"3ea57dad2cd76ae0","repo":"jackwener/OpenCLI","slug":"linkedin-connections-api-authentication-failed","errorCode":null,"errorMessage":"LinkedIn connections API authentication failed: ","messagePattern":"LinkedIn connections API authentication failed: ","errorType":"error_code","errorClass":"AuthRequiredError","httpStatus":null,"severity":"error","filePath":"clis/linkedin/connections.js","lineNumber":102,"sourceCode":"    ],\n    columns: ['rank', 'name', 'occupation', 'public_id', 'connected_at', 'url'],\n    func: async (page, kwargs) => {\n        const limit = parseLimit(kwargs.limit, 20, 500);\n        await page.goto('https://www.linkedin.com/mynetwork/invite-connect/connections/');\n        await page.wait(2);\n        await assertLinkedInAuthenticated(page, 'linkedin connections');\n        const csrf = await requireLinkedInCookie(page, 'linkedin connections');\n        const rows = [];\n        let start = 0;\n        while (rows.length < limit) {\n            const remaining = limit - rows.length;\n            const count = remaining < PAGE_SIZE ? remaining : PAGE_SIZE;\n            const url = `${CONNECTIONS_PATH}?start=${start}&count=${count}`;\n            const fetched = unwrapEvaluateResult(\n                await page.evaluate(`(${fetchConnections.toString()})(${JSON.stringify(url)}, ${JSON.stringify(csrf)})`),\n            );\n            if (fetched && fetched.authRequired) {\n                throw new AuthRequiredError(LINKEDIN_DOMAIN, 'LinkedIn connections API authentication failed: ' + fetched.error);\n            }\n            if (!fetched || fetched.error || !fetched.json) {\n                throw new CommandExecutionError('LinkedIn connections API returned an unexpected response: ' + ((fetched && fetched.error) || 'no data'));\n            }\n            const elements = fetched.json.elements;\n            if (!Array.isArray(elements)) {\n                throw new CommandExecutionError('LinkedIn connections API returned a malformed payload: missing elements array');\n            }\n            if (elements.length === 0) break;\n            for (const element of elements) {\n                rows.push(mapConnection(element, rows.length));\n                if (rows.length >= limit) break;\n            }\n            start += elements.length;\n            if (elements.length < count) break;\n        }\n        if (rows.length === 0) {\n            throw new EmptyResultError('linkedin connections', 'No LinkedIn connections were found.');","sourceCodeStart":84,"sourceCodeEnd":120,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/linkedin/connections.js#L84-L120","documentation":"The in-page fetchConnections helper calls LinkedIn's Voyager /voyager/api/relationships/connections endpoint with the session CSRF token. When it returns HTTP 401/403 or an HTML login/checkpoint body, it reports authRequired and the command throws AuthRequiredError, appending the underlying error (e.g. 'HTTP 401', 'HTML auth/checkpoint response').","triggerScenarios":"Running `linkedin connections` with expired/invalidated session cookies, a missing or stale JSESSIONID (csrf) cookie, or LinkedIn answering the API call with a login redirect / challenge page instead of JSON.","commonSituations":"Cookie jar not refreshed after LinkedIn rotated JSESSIONID; account restricted or rate-limited into a checkpoint; VPN/datacenter IP triggering the authwall; logged out in another tab.","solutions":["Re-authenticate: re-run the command and sign in when the browser opens, so fresh cookies and csrf token are captured.","Resolve any LinkedIn security checkpoint in a normal browser, then retry the CLI.","Clear cached LinkedIn cookies for the CLI and log in again from a residential IP / without VPN.","Confirm JSESSIONID exists via requireLinkedInCookie — if it is missing, the session was dropped."],"exampleFix":"// before (stale csrf/session)\nAuthRequiredError: LinkedIn connections API authentication failed: HTTP 401\n// after\n$ opencli linkedin login  # refresh session cookies\n$ opencli linkedin connections --limit 50","handlingStrategy":"try-catch","validationCode":"const cookies = await page.context().cookies('https://www.linkedin.com');\nconst hasSession = cookies.some(c => c.name === 'li_at') && cookies.some(c => c.name === 'JSESSIONID');\nif (!hasSession) throw new Error('LinkedIn session cookies (li_at / JSESSIONID) missing — authenticate first.');","typeGuard":"function isAuthRequired(result) {\n  return Boolean(result && result.authRequired);\n}","tryCatchPattern":"try {\n  const rows = await opencli.linkedin.connections({ limit: 50 });\n} catch (e) {\n  if (e.name === 'AuthRequiredError') {\n    await opencli.linkedin.login(); // interactive re-auth\n    return opencli.linkedin.connections({ limit: 50 });\n  }\n  throw e;\n}","preventionTips":["Refresh LinkedIn cookies before long or scheduled jobs.","Avoid datacenter IPs / VPNs that trigger LinkedIn authwalls.","Resolve security checkpoints immediately when LinkedIn flags the account.","Detect the appended cause ('HTTP 401/403', 'HTML auth/checkpoint response') to confirm session state."],"tags":["linkedin","authentication","http-401","cookies"],"backgroundTag":"http-401-unauthorized","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}