jackwener/OpenCLI · error · CommandExecutionError
LinkedIn connections API returned a malformed payload: missi
Error message
LinkedIn connections API returned a malformed payload: missing elements array
What it means
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.
Source
Thrown at clis/linkedin/connections.js:109
const csrf = await requireLinkedInCookie(page, 'linkedin connections');
const rows = [];
let start = 0;
while (rows.length < limit) {
const remaining = limit - rows.length;
const count = remaining < PAGE_SIZE ? remaining : PAGE_SIZE;
const url = `${CONNECTIONS_PATH}?start=${start}&count=${count}`;
const fetched = unwrapEvaluateResult(
await page.evaluate(`(${fetchConnections.toString()})(${JSON.stringify(url)}, ${JSON.stringify(csrf)})`),
);
if (fetched && fetched.authRequired) {
throw new AuthRequiredError(LINKEDIN_DOMAIN, 'LinkedIn connections API authentication failed: ' + fetched.error);
}
if (!fetched || fetched.error || !fetched.json) {
throw new CommandExecutionError('LinkedIn connections API returned an unexpected response: ' + ((fetched && fetched.error) || 'no data'));
}
const elements = fetched.json.elements;
if (!Array.isArray(elements)) {
throw new CommandExecutionError('LinkedIn connections API returned a malformed payload: missing elements array');
}
if (elements.length === 0) break;
for (const element of elements) {
rows.push(mapConnection(element, rows.length));
if (rows.length >= limit) break;
}
start += elements.length;
if (elements.length < count) break;
}
if (rows.length === 0) {
throw new EmptyResultError('linkedin connections', 'No LinkedIn connections were found.');
}
return rows;
},
});
export const __test__ = { fetchConnections, mapConnection };
View on GitHub (pinned to 49907e53dc)
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 || []).
Example fix
// before
const elements = fetched.json.elements;
if (!Array.isArray(elements)) {
throw new CommandExecutionError('LinkedIn connections API returned a malformed payload: missing elements array');
}
// after
const elements = fetched.json.elements || fetched.json.data?.elements || fetched.json['*elements'] || [];
if (!Array.isArray(elements)) throw new CommandExecutionError('...missing elements array: keys=' + Object.keys(fetched.json).join(',')); Defensive patterns
Strategy: type-guard
Validate before calling
// After a raw fetch, assert the envelope before mapping:
if (!payload || !Array.isArray(payload.elements)) {
throw new Error('Connections payload has no elements array — keys: ' + Object.keys(payload || {}).join(','));
} Type guard
function hasElementsArray(json) {
return Boolean(json) && typeof json === 'object' && Array.isArray(json.elements);
} Try / catch
try {
const rows = await opencli.linkedin.connections({ limit: 20 });
} catch (e) {
if (/malformed payload: missing elements array/.test(e.message || '')) {
console.warn('Voyager envelope changed; update the CLI or adapt the parser.');
return [];
}
throw e;
} Prevention
- 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.
When it happens
Trigger: 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).
Common situations: 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.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- LinkedIn connection miniProfile field ${field} was malformed
- returned malformed items payload
- LinkedIn connections returned an element without a miniProfi
- LinkedIn messaging API returned malformed normalized payload
- LinkedIn messaging API returned a conversation without threa
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/edbc7c060bbe357b.
Report an issue: GitHub.