{"record":{"id":"77db6c1b5907d25d","repo":"jackwener/OpenCLI","slug":"no-linkedin-learning-results-for-keywords","errorCode":null,"errorMessage":"No LinkedIn Learning results for \"${keywords}\"","messagePattern":"No LinkedIn Learning results for \"(.+?)\"","errorType":"error_code","errorClass":"EmptyResultError","httpStatus":null,"severity":"info","filePath":"clis/linkedin-learning/search.js","lineNumber":79,"sourceCode":"    ],\n    columns: ['rank', 'type', 'title', 'instructor', 'difficulty', 'duration_sec', 'rating', 'rating_count', 'viewers', 'url'],\n    func: async (page, args) => {\n        if (!page) throw new CommandExecutionError('Browser session required for linkedin-learning search');\n        const keywords = normalizeWhitespace(args.keywords);\n        if (!keywords) throw new ArgumentError('--keywords is required');\n        const limit = parseLimit(args.limit);\n\n        const url = `https://www.linkedin.com/learning-api/searchV2?keywords=${encodeURIComponent(keywords)}&q=keywords`;\n        const result = await fetchLinkedInLearningApi(page, url);\n        if (!result?.json) {\n            throw new CommandExecutionError(`LinkedIn Learning searchV2 failed: ${result?.error ?? 'no payload'}`);\n        }\n        const elements = result.json?.elements;\n        if (!Array.isArray(elements)) {\n            throw new CommandExecutionError('LinkedIn Learning searchV2 returned malformed payload: missing elements array');\n        }\n        if (elements.length === 0) {\n            throw new EmptyResultError(`No LinkedIn Learning results for \"${keywords}\"`);\n        }\n        const rows = [];\n        for (const el of elements) {\n            if (rows.length >= limit) break;\n            const row = parseRow(el, rows.length + 1);\n            if (row) rows.push(row);\n        }\n        if (rows.length === 0) {\n            throw new CommandExecutionError('LinkedIn Learning searchV2 returned no parseable rows with slug identity');\n        }\n        return rows;\n    },\n});\n\nexport const __test__ = {\n    parseAuthors,\n    durationSeconds,\n    averageRating,","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/linkedin-learning/search.js#L61-L97","documentation":"An EmptyResultError thrown when searchV2 legitimately returns an elements array that contains zero items. This is not a failure of the transport or schema — the query simply matched nothing. It lets the CLI exit with a distinct 'empty' code instead of an error.","triggerScenarios":"A keywords value that matches no LinkedIn Learning courses (misspellings, very niche or non-English terms, or terms LinkedIn does not index), or a filters/region context where no content is available to the signed-in account.","commonSituations":"Typo'd search keywords, searching for content unavailable in the account's locale/region, or content removed from the catalog.","solutions":["Simplify or broaden the --keywords value and retry.","Check spelling and try English keyword variants.","Verify in the LinkedIn Learning web UI that searching the same term returns results.","Treat as an empty result in calling scripts (check for EmptyResultError separately from real errors)."],"exampleFix":"// before\nclio linkedin-learning search --keywords \"xjs9z niche gibberish\"\n// after\nclio linkedin-learning search --keywords \"javascript\"","handlingStrategy":"try-catch","validationCode":"// sanity-check keywords before invoking\nconst kw = keywords.trim();\nif (!kw || kw.length < 2) throw new Error('Provide meaningful search keywords');","typeGuard":null,"tryCatchPattern":"try {\n  const rows = await search(page, { keywords });\n} catch (e) {\n  if (e.name === 'EmptyResultError') return []; // empty is not a failure\n  throw e;\n}","preventionTips":["Handle EmptyResultError separately from hard errors in calling scripts","Broaden or correct keywords when an empty result is returned","Cross-check the same query in the LinkedIn Learning web UI","Remember the CLI defaults --limit to 10; emptiness is about matches, not limits"],"tags":["empty-result","search","linkedin"],"backgroundTag":"empty-result-set","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}