{"record":{"id":"e7843c6c7c76bab3","repo":"jackwener/OpenCLI","slug":"label-returned-an-unexpected-response-e7843c","errorCode":null,"errorMessage":"${label} returned an unexpected response","messagePattern":"(.+?) returned an unexpected response","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/linkedin/salesnav-inbox.js","lineNumber":128,"sourceCode":"      if (!res.ok) return { error: 'HTTP ' + res.status, status: res.status, text, json };\n      return { status: res.status, json };\n    } catch (e) {\n      return { error: 'fetch failed: ' + ((e && e.message) || String(e)) };\n    }\n  })()`;\n}\n\nexport async function getCsrf(page) {\n  const cookies = await page.getCookies({ url: 'https://www.linkedin.com' });\n  const jsession = cookies.find((c) => c.name === 'JSESSIONID')?.value;\n  if (!jsession) throw new AuthRequiredError(LINKEDIN_DOMAIN, 'LinkedIn JSESSIONID cookie not found. Please sign in to LinkedIn.');\n  return jsession.replace(/^\\\"|\\\"$/g, '');\n}\n\nexport async function fetchSalesnavJson(page, csrf, url, label) {\n  const result = unwrapEvaluateResult(await page.evaluate(fetchJsonScript(url, csrf)));\n  if (result?.authRequired) throw new AuthRequiredError(LINKEDIN_DOMAIN, `${label} authentication failed (HTTP ${result.status || 'auth_required'}).`);\n  if (result?.error || !result?.json) throw new CommandExecutionError(`${label} returned an unexpected response`, `${result?.error || 'no_json'}\\n${normalizeWhitespace(result?.text || '').slice(0, 500)}`);\n  return result.json;\n}\n\nexport async function fetchInboxRows(page, { limit = DEFAULT_LIMIT, maxPages = 30 } = {}) {\n  const csrf = await getCsrf(page);\n  const rows = [];\n  const seen = new Set();\n  let pageStartsAt = '';\n  let pagesFetched = 0;\n  let hasMorePages = false;\n  while (rows.length < limit && pagesFetched < maxPages) {\n    const json = await fetchSalesnavJson(page, csrf, threadListUrl({ count: PAGE_SIZE, pageStartsAt }), 'Sales Navigator messaging threads API');\n    pagesFetched += 1;\n    const pageRows = parseSalesnavThreads(json);\n    if (pageRows.length === 0) break;\n    for (const row of pageRows) {\n      if (seen.has(row.thread_id)) continue;\n      seen.add(row.thread_id);","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/linkedin/salesnav-inbox.js#L110-L146","documentation":"This CommandExecutionError is thrown by fetchSalesnavJson when the API response neither required auth nor yielded JSON — i.e. result.error is set or result.json is missing. The detail includes the error key plus up to 500 chars of the raw text so the caller can see what actually came back.","triggerScenarios":"Calling fetchSalesnavJson when the Sales Nav endpoint returns non-JSON (HTML error page, empty body, 5xx text), an in-page fetch exception (network failure, CSP block), or a JSON envelope the script flags as error.","commonSituations":"LinkedIn serving an HTML error/challenge page; server-side 5xx during the request; wrong endpoint URL producing 404 HTML; browser context blocking the fetch (extensions/CSP); transient network failure inside page.evaluate.","solutions":["Read the error detail (result.error and first 500 chars of text) to identify the actual response","Retry the request — transient 5xx/network issues often resolve on retry with backoff","Verify the endpoint URL is current (Sales Nav API paths change) and the CSRF token was sent correctly","Check whether an HTML challenge/redirect page is being served and re-authenticate if so"],"exampleFix":"// before\nconst json = await fetchSalesnavJson(page, csrf, url, 'inbox');\n// after\nlet json;\ntry { json = await fetchSalesnavJson(page, csrf, url, 'inbox'); }\ncatch (e) { await sleep(2000); json = await fetchSalesnavJson(page, csrf, url, 'inbox'); }","handlingStrategy":"retry","validationCode":"const probe = await fetchSalesnavJson(page, csrf, healthUrl, 'healthcheck');\nif (!probe) throw new Error('Sales Nav endpoint not returning JSON; check session/endpoint');","typeGuard":"function isJsonResult(r) {\n  return !!r && typeof r === 'object' && !r.error && 'json' in r && r.json != null;\n}","tryCatchPattern":"try {\n  const json = await fetchSalesnavJson(page, csrf, url, 'inbox');\n} catch (e) {\n  if (String(e.message).includes('unexpected response')) {\n    await sleep(2000 * attempt); // backoff, log detail from e\n    return fetchSalesnavJson(page, csrf, url, 'inbox');\n  }\n  throw e;\n}","preventionTips":["Log the embedded raw-text detail to identify HTML/5xx responses","Retry transient failures with exponential backoff","Verify endpoint URLs after Sales Nav API updates","Detect login-challenge HTML in responses and trigger re-auth"],"tags":["linkedin","sales-navigator","api","malformed-response","network"],"backgroundTag":"non-json-api-response","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}