{"record":{"id":"30dfff368e379315","repo":"jackwener/OpenCLI","slug":"linkedin-search-returned-an-unexpected-response","errorCode":null,"errorMessage":"LinkedIn search returned an unexpected response","messagePattern":"LinkedIn search returned an unexpected response","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/linkedin/search.js","lineNumber":280,"sourceCode":"      });\n      if (res.status === 401 || res.status === 403) {\n        const text = await res.text();\n        return {\n          authRequired: true,\n          error: 'LinkedIn API authentication failed: HTTP ' + res.status + ' ' + text.slice(0, 200)\n        };\n      }\n      if (!res.ok) {\n        const text = await res.text();\n        return { error: 'LinkedIn API error: HTTP ' + res.status + ' ' + text.slice(0, 200) };\n      }\n      return res.json();\n    })()`);\n        if (!batch || batch.error) {\n            if (batch?.authRequired) {\n                throw new AuthRequiredError(LINKEDIN_DOMAIN, batch.error);\n            }\n            throw new CommandExecutionError(batch?.error || 'LinkedIn search returned an unexpected response');\n        }\n        const elements = Array.isArray(batch?.elements) ? batch.elements : [];\n        if (elements.length === 0)\n            break;\n        for (const element of elements) {\n            const card = element?.jobCardUnion?.jobPostingCard;\n            if (!card)\n                continue;\n            // Extract job ID from URN fields\n            const jobId = [card.jobPostingUrn, card.jobPosting?.entityUrn, card.entityUrn]\n                .filter(Boolean)\n                .map(s => String(s).match(/(\\d+)/)?.[1])\n                .find(Boolean) ?? '';\n            // Extract listed date\n            const listedItem = (card.footerItems || []).find((i) => i?.type === 'LISTED_DATE' && i?.timeAt);\n            const listed = listedItem?.timeAt ? new Date(listedItem.timeAt).toISOString().slice(0, 10) : '';\n            allJobs.push({\n                title: card.jobPostingTitle || card.title?.text || '',","sourceCodeStart":262,"sourceCodeEnd":298,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/linkedin/search.js#L262-L298","documentation":"If the page-context fetch returns null/undefined or an object without batch.error, fetchJobCards cannot interpret the response and throws this generic CommandExecutionError. It is a fallback for 'response shape we did not anticipate', e.g. evaluate serialization failures or the script returning undefined.","triggerScenarios":"page.evaluate on the Voyager fetch returns a falsy value (browser context destroyed mid-fetch, navigation, crashed renderer) or a non-error object lacking `elements` — the guard `if (!batch || batch.error)` falls through to the message 'LinkedIn search returned an unexpected response'.","commonSituations":"Page navigated or tab closed while the fetch was in flight; browser crashed or was rate-limited into an interstitial that broke evaluate; anti-bot tooling neutralizing in-page fetch; CLI/browser version mismatch corrupting evaluate return serialization.","solutions":["Re-run the command — this is frequently a transient evaluation failure; ensure the browser stays open and no navigation occurs during the search.","Check that the browser session is healthy: reload linkedin.com/jobs in the automation browser and confirm it renders normally (no crash, no challenge page).","Update the CLI and browser automation dependencies — evaluate serialization behavior can differ across versions.","If reproducible, debug by logging what page.evaluate returns for the Voyager call; the response shape may need a new handling branch."],"exampleFix":"// before (batch came back undefined because tab closed mid-fetch)\nconst batch = await page.evaluate(fetchScript);\n// after — keep the page alive and validate before continuing\nawait page.bringToFront();\nconst batch = await page.evaluate(fetchScript);\nif (!batch) throw new Error('evaluate returned nothing — is the tab still open?');","handlingStrategy":"retry","validationCode":"null","typeGuard":"const isUnexpectedLinkedInResponse = (e) =>\n  e instanceof Error && /LinkedIn search returned an unexpected response/.test(e.message);","tryCatchPattern":"async function searchWithRetry(args, tries = 2) {\n  for (let i = 0; i < tries; i++) {\n    try { return await run(['linkedin', 'search', ...args]); }\n    catch (e) {\n      if (isUnexpectedLinkedInResponse(e) && i < tries - 1) {\n        await new Promise(r => setTimeout(r, 3000));\n        continue;\n      }\n      throw e;\n    }\n  }\n}","preventionTips":["Keep the automation tab in the foreground and avoid navigating or closing it mid-search.","Update the CLI and browser driver together so evaluate serialization stays consistent.","Retry once on this transient failure before treating it as fatal.","If it reproduces consistently, reload linkedin.com in the browser to rule out challenge/interstitial pages breaking the in-page fetch."],"tags":["linkedin","api","unexpected-response","voyager","browser-automation"],"backgroundTag":"unexpected-api-response-shape","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}