jackwener/OpenCLI · error · AuthRequiredError

${context} requires an active signed-in LinkedIn browser ses

Error message

${context} requires an active signed-in LinkedIn browser session

What it means

assertLinkedInAuthenticated runs a page-evaluated probe script that detects LinkedIn's auth wall (login redirects / wall text); if the probe reports authentication is required it throws AuthRequiredError(LINKEDIN_DOMAIN, `${context} requires an active signed-in LinkedIn browser session`). It converts LinkedIn's silent auth-wall into an explicit, typed error before the command wastes effort.

Source

Thrown at clis/linkedin/search.js:162

    return /\b(sign in|log in|join linkedin)\b/.test(text) ||
        /linkedin\.com\/(login|checkpoint|authwall)/i.test(text) ||
        /\b(captcha|verification required)\b/.test(text) ||
        /(请登录|登录领英|安全验证)/.test(text);
}
function buildLinkedInAuthProbeScript() {
    return `(() => {
      const text = [
        window.location.href || '',
        document.title || '',
        document.body ? (document.body.innerText || '').slice(0, 4000) : '',
      ].join('\\n');
      return ${looksLinkedInAuthWallText.toString()}(text);
    })()`;
}
async function assertLinkedInAuthenticated(page, context) {
    const authRequired = await page.evaluate(buildLinkedInAuthProbeScript());
    if (authRequired) {
        throw new AuthRequiredError(LINKEDIN_DOMAIN, `${context} requires an active signed-in LinkedIn browser session`);
    }
}
// ── Company ID resolution (requires DOM interaction) ──────────────────
async function resolveCompanyIds(page, input) {
    const rawValues = parseCsvArg(input);
    const ids = new Set();
    const names = [];
    for (const value of rawValues) {
        if (/^\d+$/.test(value))
            ids.add(value);
        else
            names.push(value);
    }
    if (!names.length)
        return [...ids];
    const resolved = await page.evaluate(`(async () => {
    const targets = ${JSON.stringify(names)};
    const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Re-run the CLI's LinkedIn login flow in the browser session to refresh cookies, then retry.
  2. Verify manually in the browser that linkedin.com shows a signed-in feed.
  3. Add a pre-check that calls the auth probe (or assertLinkedInAuthenticated) and triggers login before batch jobs.
  4. Catch AuthRequiredError in batch loops to pause and re-authenticate rather than failing the whole run.
  5. Reduce request pace; challenge walls can be triggered by aggressive scraping.

Example fix

// before
await enrichJobDetails(page, url)   // session expired -> AuthRequiredError
// after
try {
  await enrichJobDetails(page, url)
} catch (e) {
  if (e.name === 'AuthRequiredError') {
    await login(page)               // refresh LinkedIn session
    await enrichJobDetails(page, url)
  } else throw e
}
Defensive patterns

Strategy: try-catch

Validate before calling

const authRequired = await page.evaluate(buildLinkedInAuthProbeScript()); if (authRequired) await login(page);

Type guard

null

Try / catch

try { await enrichJobDetails(page, url) } catch (e) { if (e.name === 'AuthRequiredError' || /signed-in LinkedIn browser session/.test(e.message)) { await login(page); return enrichJobDetails(page, url); } throw e; }

Prevention

When it happens

Trigger: Calling enrichJobDetails (or other probe-protected flows) while the browser session is logged out, the session cookie expired mid-run, LinkedIn served an auth wall/redirect on the job URL, or the page navigated to a login/challenge page.

Common situations: Long-running scripts whose LinkedIn session expired between commands; scraping after a password change or security challenge (2FA) invalidated cookies; running against a fresh browser profile that never logged in; LinkedIn rate-limiting into a wall that looks like an auth page.

Related errors


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