jackwener/OpenCLI · error · CommandExecutionError

Browser session required for linkedin-learning search

Error message

Browser session required for linkedin-learning search

What it means

The linkedin-learning search command requires an authenticated browser session (browser: true, COOKIE strategy) to call the learning-api searchV2 endpoint with the user's LinkedIn cookies. If func is invoked with page === null, meaning no browser session exists, this CommandExecutionError is thrown immediately, before keyword validation or any network activity.

Source

Thrown at clis/linkedin-learning/search.js:64

        url: slug ? `https://www.linkedin.com/learning/${slug}` : '',
    };
}

cli({
    site: 'linkedin-learning',
    name: 'search',
    access: 'read',
    description: 'Search LinkedIn Learning courses, videos, and learning paths by keyword',
    domain: DOMAIN,
    strategy: Strategy.COOKIE,
    browser: true,
    args: [
        { name: 'keywords', type: 'string', required: true, positional: true, help: 'Search keywords, e.g. "AI agent"' },
        { name: 'limit', type: 'int', default: 10, help: `Maximum results to return (1-${MAX_LIMIT})` },
    ],
    columns: ['rank', 'type', 'title', 'instructor', 'difficulty', 'duration_sec', 'rating', 'rating_count', 'viewers', 'url'],
    func: async (page, args) => {
        if (!page) throw new CommandExecutionError('Browser session required for linkedin-learning search');
        const keywords = normalizeWhitespace(args.keywords);
        if (!keywords) throw new ArgumentError('--keywords is required');
        const limit = parseLimit(args.limit);

        const url = `https://www.linkedin.com/learning-api/searchV2?keywords=${encodeURIComponent(keywords)}&q=keywords`;
        const result = await fetchLinkedInLearningApi(page, url);
        if (!result?.json) {
            throw new CommandExecutionError(`LinkedIn Learning searchV2 failed: ${result?.error ?? 'no payload'}`);
        }
        const elements = result.json?.elements;
        if (!Array.isArray(elements)) {
            throw new CommandExecutionError('LinkedIn Learning searchV2 returned malformed payload: missing elements array');
        }
        if (elements.length === 0) {
            throw new EmptyResultError(`No LinkedIn Learning results for "${keywords}"`);
        }
        const rows = [];
        for (const el of elements) {

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Run the command through the normal CLI entry point so the Playwright page is provisioned and passed in.
  2. Install/repair Playwright browser binaries (npx playwright install) so session bootstrap succeeds.
  3. Confirm you are logged in to linkedin.com in the session, since search relies on shared cookies.
Defensive patterns

Strategy: try-catch

Validate before calling

if (!browserPage) {
  throw new Error('linkedin-learning search requires a browser session; launch one first');
}

Type guard

function hasBrowserPage(p) { return p !== null && p !== undefined && typeof p.goto === 'function'; }

Try / catch

try {
  await runCommand('linkedin-learning', 'search', [keywords]);
} catch (e) {
  if (String(e.message).includes('Browser session required')) {
    await launchBrowserAndLogin(); // then retry
  } else throw e;
}

Prevention

When it happens

Trigger: Invoking the search command through a code path that doesn't launch a browser (direct func call, harness passing null, browser startup disabled/failed) so func's page parameter is null.

Common situations: Playwright browsers not installed in a fresh CI container; running in an environment that forbids browser launch; bypassing the CLI bootstrap when calling the command function programmatically.

Related errors


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