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

  1. Update the CLI to the latest version in case the endpoint or parser was fixed.
  2. Log fetched.json (Object.keys) to see where the array moved and report/file an issue.
  3. Retry later — schema A/B tests sometimes flip back.
  4. 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

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

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/edbc7c060bbe357b. Report an issue: GitHub.