jackwener/OpenCLI · error · CommandExecutionError

LinkedIn messaging API returned an unexpected response:

Error message

LinkedIn messaging API returned an unexpected response: 

What it means

If the messaging API call neither requested auth nor returned usable JSON (fetch failed, non-JSON response, or returned an error field), the CLI throws a CommandExecutionError describing the unexpected response, appending fetched.error or 'no data'. It guards downstream parsers from undefined payloads.

Solutions

  1. Read the appended detail ('no data' vs fetched.error) to distinguish network failure from an API error body.
  2. Retry the command — transient fetch failures are the most common cause.
  3. Verify the account/API works by loading messaging manually in the profile; check for LinkedIn incident/429 responses.
  4. If persistent with a working session, the API response shape likely changed — update the library.

Example fix

// before
const convos = await inbox(); // CommandExecutionError: unexpected response

// after
try { const convos = await inbox(); }
catch (e) {
  if (e instanceof CommandExecutionError) await sleep(5000), retry();
  else throw e;
}
Defensive patterns

Strategy: retry

Validate before calling

async function apiHealthy() {
  try {
    const r = await fetch('https://www.linkedin.com/voyager/api/identity', { headers: { 'csrf-token': csrf } });
    return r.status !== 502 && r.status !== 503;
  } catch { return false; }
}

Type guard

const isUnexpectedApiResponse = (e) => e instanceof CommandExecutionError && /unexpected response/i.test(e?.message || '');

Try / catch

try {
  return await linkedinInbox();
} catch (e) {
  if (isUnexpectedApiResponse(e)) return retry(linkedinInbox, { attempts: 3, backoff: 'exponential' });
  throw e;
}

Prevention

When it happens

Trigger: During `linkedin inbox`, unwrapEvaluateResult(page.evaluate(fetchMessagingApi(...))) yields null/undefined, an object with an error property, or no json field — e.g. network failure inside the page, HTTP 5xx, or HTML error page instead of JSON.

Common situations: LinkedIn rate limiting with an HTML/JSON error body, transient network drop inside the browser, LinkedIn API returning an unexpected shape after a version change, or the evaluated fetch being blocked by CSP/extensions.

Related errors


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

Appendix: source

Thrown at clis/linkedin/inbox.js:201

    }

    const cookies = await page.getCookies({ url: 'https://www.linkedin.com' });
    const jsession = cookies.find((c) => c.name === 'JSESSIONID')?.value;
    if (!jsession) {
      throw new AuthRequiredError(LINKEDIN_DOMAIN, 'LinkedIn JSESSIONID cookie not found. Please sign in to LinkedIn.');
    }
    const csrf = jsession.replace(/^"|"$/g, '');

    // Widen the page size to the requested limit where the query supports it.
    const targetUrl = located.url.replace(/count:\d+/, 'count:' + limit);
    const fetched = unwrapEvaluateResult(
      await page.evaluate(`(${fetchMessagingApi.toString()})(${JSON.stringify(targetUrl)}, ${JSON.stringify(csrf)})`),
    );
    if (fetched && fetched.authRequired) {
      throw new AuthRequiredError(LINKEDIN_DOMAIN, 'LinkedIn messaging API authentication failed: ' + fetched.error);
    }
    if (!fetched || fetched.error || !fetched.json) {
      throw new CommandExecutionError(
        'LinkedIn messaging API returned an unexpected response: ' + ((fetched && fetched.error) || 'no data'),
      );
    }

    let conversations = parseConversations(fetched.json, located.mailboxUrn || '');
    if (unreadOnly) conversations = conversations.filter((c) => c.unread);
    if (conversations.length === 0) {
      if (unreadOnly) return [];
      throw new EmptyResultError('linkedin inbox', 'No LinkedIn conversations were found in the inbox.');
    }

    return conversations.slice(0, limit).map((c, index) => ({
      rank: index + 1,
      thread_url: threadUrl(c.thread_id),
      thread_id: c.thread_id,
      person_name: c.person_name,
      last_message_preview: c.last_message_preview,
      unread: c.unread,

View on GitHub (pinned to 49907e53dc)