jackwener/OpenCLI · error · CommandExecutionError

LinkedIn thread history did not stabilize before --max-scrol

Error message

LinkedIn thread history did not stabilize before --max-scrolls; refusing to return a partial snapshot.

What it means

thread-snapshot scrolls the thread upward to load older messages and requires scroll history to stabilize (discovery.scrollStable === true) before returning. If it consumed maxScrolls (default 30, and >= 4) attempts without the message history settling, it refuses to return a partial snapshot and throws this CommandExecutionError.

Source

Thrown at clis/linkedin/thread-snapshot.js:347

          scrollStable: firstDiscovery.scrollStable,
        };
      } else {
        discovery = retried;
      }
    }
    if (discovery?.authRequired) {
      throw new AuthRequiredError(LINKEDIN_DOMAIN, 'LinkedIn thread-snapshot requires an active signed-in LinkedIn browser session.');
    }
    if (!discovery || typeof discovery !== 'object' || Array.isArray(discovery) || !Array.isArray(discovery.apiUrls)) {
      throw new CommandExecutionError('LinkedIn thread-snapshot returned a malformed API discovery payload.');
    }

    const actualUrl = canonicalizeLinkedInThreadUrl(discovery.url || '');
    if (threadUrl && actualUrl && threadUrl !== actualUrl) {
      throw new CommandExecutionError('LinkedIn thread-snapshot blocked: thread_url_mismatch', `Expected ${threadUrl}; actual ${actualUrl}`);
    }
    if (maxScrolls >= 4 && discovery.scrollAttempts >= maxScrolls && discovery.scrollStable === false) {
      throw new CommandExecutionError('LinkedIn thread history did not stabilize before --max-scrolls; refusing to return a partial snapshot.');
    }

    const apiUrls = validateThreadApiUrls(discovery.apiUrls, threadUrl);
    const csrf = await requireLinkedInCookie(page, 'LinkedIn thread-snapshot');
    const fetched = unwrapEvaluateResult(
      await page.evaluate(buildFetchThreadPagesScript(apiUrls, csrf)),
    );
    if (fetched?.authRequired) {
      throw new AuthRequiredError(LINKEDIN_DOMAIN, `LinkedIn messengerMessages API authentication failed: ${fetched.error}`);
    }
    if (!fetched || fetched.error || !Array.isArray(fetched.pages)) {
      throw new CommandExecutionError(`LinkedIn messengerMessages API returned an unexpected response: ${fetched?.error || 'no data'}`);
    }

    const parsed = parseThreadPages(fetched.pages);
    const recipient = parsed.recipientNames.join(', ');
    const latestMessageText = parsed.messages[parsed.messages.length - 1]?.text || '';
    const normalized = {

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Increase --max-scrolls (e.g. 60 or 100) to give the thread more room to load its full history
  2. Improve network conditions or retry later if LinkedIn is throttling the pagination API
  3. Accept a truncated view only for short threads where stabilization isn't needed
  4. Re-run the command; scroll state is not cached so a retry starts fresh

Example fix

// before
linkedin thread-snapshot --thread-url <url> --max-scrolls 10
// after
linkedin thread-snapshot --thread-url <url> --max-scrolls 100
Defensive patterns

Strategy: retry

Validate before calling

// Estimate thread length first; long threads need a high max-scrolls
const maxScrolls = estimatedMessageCount > 200 ? 100 : 30;

Try / catch

try {
  await threadSnapshot({ threadUrl, maxScrolls });
} catch (e) {
  if (String(e.message).includes('did not stabilize')) {
    await threadSnapshot({ threadUrl, maxScrolls: maxScrolls * 2 }); // retry with more headroom
  } else throw e;
}

Prevention

When it happens

Trigger: Running thread-snapshot on a very long thread where LinkedIn loads older pages lazily and scrollAttempts reaches --max-scrolls with scrollStable still false — e.g. slow network, heavy thread, or aggressive throttling of the messengerMessages pagination API.

Common situations: Snapshotting multi-year conversations with thousands of messages; slow/limited connectivity causing lazy-load requests to time out; setting --max-scrolls too low (e.g. 5) on a long thread; LinkedIn rate-limiting the pagination endpoint.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/7aba83d99c750d97. Report an issue: GitHub.