{"record":{"id":"a93dc76e56ca16ac","repo":"jackwener/OpenCLI","slug":"linkedin-timeline","errorCode":null,"errorMessage":"linkedin timeline","messagePattern":"linkedin timeline","errorType":"exception","errorClass":"EmptyResultError","httpStatus":null,"severity":"warning","filePath":"clis/linkedin/timeline.js","lineNumber":498,"sourceCode":"        await page.goto('https://www.linkedin.com/feed/');\n        await page.wait(4);\n        let posts = [];\n        let sawLoginWall = false;\n        for (let i = 0; i < 6 && posts.length < limit; i++) {\n            const batch = await extractVisiblePosts(page);\n            if (batch?.loginRequired)\n                sawLoginWall = true;\n            posts = mergeTimelinePosts(posts, Array.isArray(batch?.posts) ? batch.posts : []);\n            if (posts.length >= limit)\n                break;\n            await page.autoScroll({ times: 1, delayMs: 1200 });\n            await page.wait(1);\n        }\n        if (sawLoginWall && posts.length === 0) {\n            throw new AuthRequiredError('linkedin.com', 'LinkedIn timeline requires an active signed-in browser session');\n        }\n        if (posts.length === 0) {\n            throw new EmptyResultError('linkedin timeline', 'Make sure your LinkedIn home feed is visible in the browser.');\n        }\n        return posts.slice(0, limit).map((post, index) => ({\n            rank: index + 1,\n            ...post,\n        }));\n    },\n});\nexport const __test__ = {\n    parseMetric,\n    buildPostId,\n    mergeTimelinePosts,\n    normalizeTimestamp,\n};\n","sourceCodeStart":480,"sourceCodeEnd":512,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/linkedin/timeline.js#L480-L512","documentation":"If the LinkedIn home feed rendered but yielded zero posts after scrolling (and no login wall was seen), the timeline command throws EmptyResultError for 'linkedin timeline', telling the user to make sure the feed is visible — the command never returns an empty list silently.","triggerScenarios":"page loads the feed, scrolling completes, posts.length === 0 with sawLoginWall false — e.g. selectors no longer matching a redesigned feed, feed region showing 'no posts yet' for a brand-new account, or the feed hidden behind an overlay/onboarding modal.","commonSituations":"New LinkedIn accounts with empty feeds; LinkedIn A/B tests changing feed markup so scraping selectors match nothing; onboarding or cookie-consent dialogs covering the feed; very restrictive feeds due to follow/graph settings.","solutions":["Open LinkedIn in the browser and confirm posts are actually visible in the home feed","Dismiss any onboarding/cookie-consent overlays in the browser session and retry","Update the CLI to the latest version if LinkedIn changed feed markup","Wait and retry if the account/feed is brand-new or temporarily empty"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"// Verify feed posts exist in the DOM before invoking\nconst hasPosts = await page.evaluate(() => document.querySelectorAll('.feed-shared-update-v2, article').length > 0);\nif (!hasPosts) console.warn('Feed appears empty; result may be an EmptyResultError');","typeGuard":null,"tryCatchPattern":"try {\n  return await linkedinTimeline({ limit });\n} catch (e) {\n  if (String(e.message).includes('linkedin timeline')) {\n    // fall back to a saved/cached result or surface guidance to the user\n    return cache.get('timeline') ?? [];\n  } else throw e;\n}","preventionTips":["Dismiss onboarding/cookie overlays in the browser session first","Confirm the account's feed actually shows posts manually","Update the CLI when LinkedIn redesigns feed markup","Wait for newer accounts to accumulate feed content before scraping"],"tags":["linkedin","empty-result","scraping","browser-automation"],"backgroundTag":"empty-result-set","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}