{"record":{"id":"438fcdf051a72047","repo":"jackwener/OpenCLI","slug":"label-returned-malformed-response","errorCode":null,"errorMessage":"${label} returned malformed response","messagePattern":"(.+?) returned malformed response","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/linkedin/salesnav-message.js","lineNumber":168,"sourceCode":"    }\n  })()`;\n}\n\nfunction requireFetchResult(result, label, { requireJson = true } = {}) {\n  if (Array.isArray(result)) {\n    const [kind, status, json, text, error] = result;\n    result = {\n      authRequired: kind === 'auth',\n      error: kind === 'error' ? error || `HTTP ${status}` : '',\n      status,\n      json,\n      text,\n    };\n  }\n  if (result?.authRequired) throw new AuthRequiredError(LINKEDIN_DOMAIN, `${label} auth failed.`);\n  if (result?.error) throw new CommandExecutionError(`${label} failed`, result.error);\n  if (!result || typeof result !== 'object' || Array.isArray(result)) {\n    throw new CommandExecutionError(`${label} returned malformed response`);\n  }\n  if (requireJson && (!result.json || typeof result.json !== 'object' || Array.isArray(result.json))) {\n    throw new CommandExecutionError(`${label} returned malformed response`, 'missing_json');\n  }\n  return result;\n}\n\nfunction salesPageShowsSentMessage(text, recipientName) {\n  const normalizedText = normalizeWhitespace(text);\n  const firstName = normalizeWhitespace(recipientName).split(' ')[0];\n  return normalizedText.includes('You sent a Sales Navigator message')\n    && (!firstName || normalizedText.includes(firstName));\n}\n\nasync 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.');","sourceCodeStart":150,"sourceCodeEnd":186,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/linkedin/salesnav-message.js#L150-L186","documentation":"requireFetchResult expects a plain object response; if the fetch result is null, not an object, or an array, it throws CommandExecutionError('...returned malformed response'). This guards against empty bodies, HTML login pages, or unexpected non-JSON payloads from the Sales Navigator endpoints.","triggerScenarios":"A fetch returns an empty/HTML body (redirect to login or challenge page), or the unwrapped response is an array instead of an object — checked in profileResult, creditsResult, sendResult, creditsAfterResult.","commonSituations":"LinkedIn serving an anti-bot interstitial instead of API JSON; network proxy returning HTML error pages; hitting the API before the Sales Nav session is fully established; LinkedIn schema change altering the envelope.","solutions":["Print/capture result.text to see what LinkedIn actually returned","Re-authenticate if the body is a login/HTML page","Add a delay after page.goto(SALES_HOME) before API calls so the session settles","Update parsing if LinkedIn changed the response envelope"],"exampleFix":"null","handlingStrategy":"try-catch","validationCode":"const res = await fetchProfile(url);\nif (res.status >= 400 || /<html/i.test(res.text || '')) throw new Error('non-JSON response: ' + res.status);","typeGuard":"const isPlainObject = (v) => v !== null && typeof v === 'object' && !Array.isArray(v);","tryCatchPattern":"try {\n  const r = await fetchProfileData(page, urn);\n} catch (err) {\n  if (/malformed response/.test(err.message)) {\n    await page.wait(3); await reauthenticateIfLoginScreen(page); return retry();\n  }\n  throw err;\n}","preventionTips":["Check result.text when it fails — HTML means login/challenge page","Throttle request rate to avoid anti-bot interstitials","Refresh the session before batch runs","Pin/update parsing code when LinkedIn changes its envelope"],"tags":["linkedin","malformed-response","sales-navigator","html-response"],"backgroundTag":"malformed-api-response","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}