jackwener/OpenCLI · error · CommandExecutionError

LinkedIn connections API returned an unexpected response:

Error message

LinkedIn connections API returned an unexpected response: 

What it means

If the Voyager connections fetch yields neither authRequired nor valid JSON (fetched falsy, fetched.error set, or fetched.json missing), the command throws CommandExecutionError with the underlying error string. It means the request completed abnormally but was not an authentication problem.

Source

Thrown at clis/linkedin/connections.js:105

        const limit = parseLimit(kwargs.limit, 20, 500);
        await page.goto('https://www.linkedin.com/mynetwork/invite-connect/connections/');
        await page.wait(2);
        await assertLinkedInAuthenticated(page, 'linkedin connections');
        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;
    },

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Read the appended cause in the message ('HTTP 429', 'fetch failed: ...') and address that specific condition.
  2. If HTTP 429, wait several minutes and retry with a smaller --limit to reduce page count.
  3. For HTTP 5xx, retry later or check linkedin.com status; it is server-side.
  4. Retry once after reloading; transient in-page fetch failures usually clear on a fresh navigation.

Example fix

// before (aggressive pagination)
$ opencli linkedin connections --limit 500
CommandExecutionError: LinkedIn connections API returned an unexpected response: HTTP 429
// after
$ opencli linkedin connections --limit 40  # fewer requests, spaced out
Defensive patterns

Strategy: retry

Validate before calling

// No pre-call validation possible for transient HTTP failures; check connectivity first.
if (!(await fetch('https://www.linkedin.com', { method: 'HEAD' })).ok) {
  throw new Error('linkedin.com unreachable — fix network before calling connections.');
}

Type guard

function isTransientHttpFailure(message) {
  return /HTTP (429|5\d\d)|fetch failed/i.test(message || '');
}

Try / catch

try {
  const rows = await opencli.linkedin.connections({ limit: 20 });
} catch (e) {
  if (/unexpected response/.test(e.message || '')) {
    if (/HTTP 429/.test(e.message)) await new Promise(r => setTimeout(r, 5 * 60_000));
    return opencli.linkedin.connections({ limit: 20 }); // single retry
  }
  throw e;
}

Prevention

When it happens

Trigger: fetchConnections returns { error: 'HTTP 429' } (rate limit), { error: 'HTTP 5xx' } (server error), { error: 'response was not valid JSON' }, or { error: 'fetch failed: ...' } from a network-level failure inside the page.

Common situations: LinkedIn rate-limiting aggressive pagination (HTTP 429); transient 5xx during a LinkedIn incident; page context destroyed mid-fetch (navigation/close) causing 'fetch failed'; corporate proxy intercepting the response.

Related errors


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