{"record":{"id":"58b9d5478e945e37","repo":"jackwener/OpenCLI","slug":"browser-session-required-for-linkedin-thread-snaps","errorCode":null,"errorMessage":"Browser session required for linkedin thread-snapshot","messagePattern":"Browser session required for linkedin thread-snapshot","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/linkedin/thread-snapshot.js","lineNumber":313,"sourceCode":"  return { recipientNames, messages };\n}\n\ncli({\n  site: 'linkedin',\n  name: 'thread-snapshot',\n  access: 'read',\n  description: 'Load a LinkedIn messaging thread and return a structured conversation snapshot',\n  domain: LINKEDIN_DOMAIN,\n  strategy: Strategy.COOKIE,\n  browser: true,\n  args: [\n    { name: 'thread-url', required: true, help: 'Exact LinkedIn messaging thread URL to open and snapshot' },\n    { name: 'max-scrolls', type: 'number', default: 30, help: 'Maximum upward scroll attempts used to request older message pages' },\n    { name: 'json', type: 'bool', default: false, help: 'Return only JSON snapshot string in the snapshot_json field' },\n  ],\n  columns: ['thread_url', 'recipient', 'message_count', 'latest_text', 'snapshot_json'],\n  func: async (page, args) => {\n    if (!page) throw new CommandExecutionError('Browser session required for linkedin thread-snapshot');\n    const threadUrl = requireLinkedInThreadUrl(requireStringArg(args, 'thread-url', '--thread-url'), '--thread-url');\n    const maxScrolls = parseMaxScrolls(args['max-scrolls']);\n\n    await page.goto(threadUrl);\n    await page.wait(10);\n\n    let discovery = unwrapEvaluateResult(await page.evaluate(buildThreadApiDiscoveryScript(maxScrolls)));\n    if (discovery && Array.isArray(discovery.apiUrls) && discovery.apiUrls.length === 0) {\n      const firstDiscovery = discovery;\n      await page.wait(4);\n      const retried = unwrapEvaluateResult(await page.evaluate(buildThreadApiDiscoveryScript(0)));\n      if (retried && typeof retried === 'object' && !Array.isArray(retried)) {\n        discovery = {\n          ...retried,\n          scrollAttempts: firstDiscovery.scrollAttempts,\n          scrollStable: firstDiscovery.scrollStable,\n        };\n      } else {","sourceCodeStart":295,"sourceCodeEnd":331,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/linkedin/thread-snapshot.js#L295-L331","documentation":"The thread-snapshot command runs a real browser page to open the thread, scroll, and intercept messengerMessages API responses. It throws this CommandExecutionError when the cli func is invoked with a null/undefined page, meaning no browser session was created or passed in.","triggerScenarios":"Calling the command without an active browser session — e.g. invoking func directly with no page, or running through a harness that doesn't allocate a browser for browser:true commands.","commonSituations":"Forgetting to launch the browser session before executing the command in scripts/tests; a session pool exhausted or closed before the call; misconfigured runner that skips browser setup for LinkedIn commands.","solutions":["Start/attach a browser session (with a signed-in LinkedIn profile) before invoking the command","Check your runner/harness so browser:true commands receive a live page object","If the session crashed, re-launch it and re-run the command","In scripts, assert the page exists before calling the CLI func"],"exampleFix":"// before\nawait linkedinThreadSnapshot.func(null, args);\n// after\nconst page = await browserSession.acquire('linkedin');\nawait linkedinThreadSnapshot.func(page, args);","handlingStrategy":"type-guard","validationCode":"if (!page || typeof page.goto !== 'function') {\n  throw new Error('Launch a browser session before running linkedin thread-snapshot');\n}","typeGuard":"const hasLivePage = (page) => !!page && typeof page.goto === 'function' && typeof page.wait === 'function';","tryCatchPattern":"try {\n  const snap = await run('linkedin thread-snapshot', { 'thread-url': url });\n} catch (err) {\n  if (String(err.message).includes('Browser session required')) {\n    const page = await browserSession.acquire('linkedin');\n    // retry with an allocated page\n  } else throw err;\n}","preventionTips":["Always allocate the browser session before browser:true commands","Acquire the page and run the command in the same scope so it can't be closed early","Assert page presence in test harnesses that call cli funcs directly"],"tags":["linkedin","browser-session","precondition"],"backgroundTag":"browser-session-required","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}