{"record":{"id":"edbc7c060bbe357b","repo":"jackwener/OpenCLI","slug":"linkedin-connections-api-returned-a-malformed-payl","errorCode":null,"errorMessage":"LinkedIn connections API returned a malformed payload: missing elements array","messagePattern":"LinkedIn connections API returned a malformed payload: missing elements array","errorType":"error_code","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/linkedin/connections.js","lineNumber":109,"sourceCode":"        const csrf = await requireLinkedInCookie(page, 'linkedin connections');\n        const rows = [];\n        let start = 0;\n        while (rows.length < limit) {\n            const remaining = limit - rows.length;\n            const count = remaining < PAGE_SIZE ? remaining : PAGE_SIZE;\n            const url = `${CONNECTIONS_PATH}?start=${start}&count=${count}`;\n            const fetched = unwrapEvaluateResult(\n                await page.evaluate(`(${fetchConnections.toString()})(${JSON.stringify(url)}, ${JSON.stringify(csrf)})`),\n            );\n            if (fetched && fetched.authRequired) {\n                throw new AuthRequiredError(LINKEDIN_DOMAIN, 'LinkedIn connections API authentication failed: ' + fetched.error);\n            }\n            if (!fetched || fetched.error || !fetched.json) {\n                throw new CommandExecutionError('LinkedIn connections API returned an unexpected response: ' + ((fetched && fetched.error) || 'no data'));\n            }\n            const elements = fetched.json.elements;\n            if (!Array.isArray(elements)) {\n                throw new CommandExecutionError('LinkedIn connections API returned a malformed payload: missing elements array');\n            }\n            if (elements.length === 0) break;\n            for (const element of elements) {\n                rows.push(mapConnection(element, rows.length));\n                if (rows.length >= limit) break;\n            }\n            start += elements.length;\n            if (elements.length < count) break;\n        }\n        if (rows.length === 0) {\n            throw new EmptyResultError('linkedin connections', 'No LinkedIn connections were found.');\n        }\n        return rows;\n    },\n});\n\nexport const __test__ = { fetchConnections, mapConnection };\n","sourceCodeStart":91,"sourceCodeEnd":127,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/linkedin/connections.js#L91-L127","documentation":"After a successful JSON response, the command asserts fetched.json.elements is an array. If LinkedIn returns a 200 JSON body whose shape changed (no elements array), CommandExecutionError is thrown because pagination and mapping are impossible.","triggerScenarios":"Voyager returns a JSON error envelope, a paging-only object, or a schema where the list lives at another key (e.g. after a LinkedIn API version bump or x-restli-protocol-version mismatch).","commonSituations":"LinkedIn deprecating the legacy relationships endpoint or A/B testing a new response envelope; hitting a different regional endpoint that returns wrapped JSON; protocol version header no longer accepted silently.","solutions":["Update the CLI to the latest version in case the endpoint or parser was fixed.","Log fetched.json (Object.keys) to see where the array moved and report/file an issue.","Retry later — schema A/B tests sometimes flip back.","Locally adapt: const elements = Array.isArray(fetched.json.elements) ? fetched.json.elements : (fetched.json.data?.elements || fetched.json._included || [])."],"exampleFix":"// before\nconst elements = fetched.json.elements;\nif (!Array.isArray(elements)) {\n    throw new CommandExecutionError('LinkedIn connections API returned a malformed payload: missing elements array');\n}\n// after\nconst elements = fetched.json.elements || fetched.json.data?.elements || fetched.json['*elements'] || [];\nif (!Array.isArray(elements)) throw new CommandExecutionError('...missing elements array: keys=' + Object.keys(fetched.json).join(','));","handlingStrategy":"type-guard","validationCode":"// After a raw fetch, assert the envelope before mapping:\nif (!payload || !Array.isArray(payload.elements)) {\n  throw new Error('Connections payload has no elements array — keys: ' + Object.keys(payload || {}).join(','));\n}","typeGuard":"function hasElementsArray(json) {\n  return Boolean(json) && typeof json === 'object' && Array.isArray(json.elements);\n}","tryCatchPattern":"try {\n  const rows = await opencli.linkedin.connections({ limit: 20 });\n} catch (e) {\n  if (/malformed payload: missing elements array/.test(e.message || '')) {\n    console.warn('Voyager envelope changed; update the CLI or adapt the parser.');\n    return [];\n  }\n  throw e;\n}","preventionTips":["Keep the CLI updated; endpoint shape changes are fixed upstream.","Log response top-level keys when this fires to diagnose schema drift fast.","Pin the x-restli-protocol-version behavior by testing against a captured payload in CI."],"tags":["linkedin","schema-validation","api-change"],"backgroundTag":"unexpected-api-schema","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}