jackwener/OpenCLI · critical · AuthRequiredError
LinkedIn Sales Navigator API auth failed (HTTP ' + (result.s
Error message
LinkedIn Sales Navigator API auth failed (HTTP ' + (result.status || '') + '). Confirm the account has Sales Navigator access.
What it means
requireLeadSearchResult inspects the in-page fetch result and throws AuthRequiredError when result.authRequired is true, i.e. the salesApiLeadSearch endpoint answered 401 or 403 (see fetchLeadSearchScript line 53). This means the browser session is not authenticated to Sales Navigator or lacks the Sales Navigator entitlement, so the search cannot proceed.
Source
Thrown at clis/linkedin/salesnav-search.js:112
throw new CommandExecutionError('Sales Navigator lead row missing profile identity');
}
leads.push({
name,
title: normalizeWhitespace(pos.title || ''),
company: normalizeWhitespace(pos.companyName || ''),
location: normalizeWhitespace(el.geoRegion || ''),
degree: normalizeWhitespace(el.degree || ''),
profile_url: profileUrlFromEntityUrn(entityUrn),
lead_url: leadUrlFromEntityUrn(entityUrn),
recipient_urn: entityUrn,
});
}
return leads;
}
function requireLeadSearchResult(result) {
if (result?.authRequired) {
throw new AuthRequiredError(LINKEDIN_DOMAIN, 'LinkedIn Sales Navigator API auth failed (HTTP ' + (result.status || '') + '). Confirm the account has Sales Navigator access.');
}
if (result?.error) {
throw new CommandExecutionError('Sales Navigator lead search API returned an unexpected response', result.error);
}
if (!result || !result.json) {
throw new CommandExecutionError('Sales Navigator lead search API returned an unexpected response', 'no_json');
}
return result.json;
}
cli({
site: 'linkedin',
name: 'salesnav-search',
access: 'read',
description: 'Search LinkedIn Sales Navigator for people leads by keyword',
domain: LINKEDIN_DOMAIN,
strategy: Strategy.UI,
browser: true,View on GitHub (pinned to 49907e53dc)
Solutions
- Open the automation browser and sign in to LinkedIn again (verify JSESSIONID cookie exists and is fresh) — the code already checks this at line 144-149, so a 401 despite the cookie means rotation mid-run: re-run the command.
- Confirm the account actually has an active Sales Navigator license (Settings → Sales Navigator); a 403 on sales-api usually means no entitlement.
- Log in to https://www.linkedin.com/sales/ manually once in the same browser profile to establish the Sales Navigator session, then retry.
- Slow down / add delay between page requests — aggressive pagination can trigger 403 throttling.
- Check whether LinkedIn changed sales-api access; try the same query in the Sales Navigator UI to confirm the account works interactively.
Example fix
// before (retrying blindly with a stale session)
const result = unwrapEvaluateResult(await page.evaluate(fetchLeadSearchScript(url, csrf)));
const json = requireLeadSearchResult(result);
// after
catch (e) {
if (e instanceof AuthRequiredError) {
await page.goto(SALES_HOME);
await page.wait(10); // give user/login flow time to (re)establish session, then retry once
const retry = unwrapEvaluateResult(await page.evaluate(fetchLeadSearchScript(url, csrf)));
const json = requireLeadSearchResult(retry);
} else {
throw e;
}
} Defensive patterns
Strategy: try-catch
Validate before calling
// before invoking, confirm session prerequisites in your own harness:
const cookies = await page.getCookies({ url: 'https://www.linkedin.com' });
const hasSession = cookies.some((c) => c.name === 'JSESSIONID');
// and confirm Sales Navigator access by loading:
// https://www.linkedin.com/sales/ and checking it does not redirect to a paywall/login Type guard
function isAuthFailure(result) {
return !!result && typeof result === 'object' && result.authRequired === true;
} Try / catch
import { AuthRequiredError } from '@jackwener/opencli/errors';
try {
const json = requireLeadSearchResult(result);
} catch (e) {
if (e instanceof AuthRequiredError) {
// prompt re-login in the automation browser, then retry the command once
console.error('Sales Navigator session invalid or missing entitlement:', e.message);
} else {
throw e;
}
} Prevention
- Always sign in to LinkedIn (and open /sales/ once) in the automation browser profile before running searches.
- Keep the Sales Navigator subscription active — 403 means no entitlement even with a valid session.
- Re-authenticate when JSESSIONID expires; long-running jobs should re-check cookies per run.
- Space out search requests to avoid LinkedIn soft-blocking sales-api with 403.
- Catch AuthRequiredError distinctly from CommandExecutionError so login issues are surfaced to the user.
When it happens
Trigger: The cli 'salesnav-search' command evaluates fetchLeadSearchScript in the page and the response status is 401 (stale/expired JSESSIONID csrf token or logged-out session) or 403 (logged in but no Sales Navigator seat, or LinkedIn blocking the sales-api call).
Common situations: LinkedIn session expired or was logged out between commands; CSRF token mismatch after JSESSIONID rotation; account downgraded or trial of Sales Navigator ended; LinkedIn rate-limiting or temporarily blocking sales-api requests with 403; corporate SSO session requiring re-login.
Related errors
- Manus /api/auth/session HTTP ${r.status}
- Zhihu /api/v4/me returned HTTP ${status} — anonymous
- www.zhihu.com
- Bilibili creator-center login is required: ${detail}
- bbs.hupu.com
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/0776a579ee764349.
Report an issue: GitHub.