jackwener/OpenCLI · error · Error

${label} returned invalid JSON

Error message

${label} returned invalid JSON

What it means

readInstagramJson wraps response.json() inside the profile.js evaluate script. If the HTTP response body cannot be parsed as JSON (HTML error page, empty body, encoding issues), it throws '<label> returned invalid JSON' where label identifies which Instagram endpoint failed (web_profile_info, feed-by-username, or users info).

Source

Thrown at clis/instagram/profile.js:26

    args: [
        { name: 'username', required: true, positional: true, help: 'Instagram username' },
    ],
    columns: ['username', 'name', 'followers', 'following', 'posts', 'verified', 'bio'],
    pipeline: [
        { navigate: 'https://www.instagram.com' },
        { evaluate: `(async () => {
  const username = \${{ args.username | json }};
  const opts = { credentials: 'include', headers: { 'X-IG-App-ID': '936619743392459' } };
  function normalizeInstagramUserId(value, label) {
    const id = typeof value === 'number' ? String(value) : (typeof value === 'string' ? value.trim() : '');
    if (!/^\\d+$/.test(id)) throw new Error(label);
    return id;
  }
  async function readInstagramJson(response, label) {
    try {
      return await response.json();
    } catch {
      throw new Error(label + ' returned invalid JSON');
    }
  }
  function throwInstagramHttpError(response, label) {
    if (response.status === 404) throw new Error('User not found: ' + username);
    if (response.status === 401 || response.status === 403) {
      throw new Error('HTTP ' + response.status + ' - make sure you are logged in to Instagram');
    }
    throw new Error(label + ' failed: HTTP ' + response.status);
  }
  function mapProfileUser(u, countFields) {
    if (!u || typeof u !== 'object' || typeof u.username !== 'string' || !u.username.trim()) {
      throw new Error('Instagram profile returned malformed user payload for: ' + username);
    }
    return {
      username: u.username,
      name: typeof u.full_name === 'string' ? u.full_name : '',
      bio: (typeof u.biography === 'string' ? u.biography : '').replace(/\\n/g, ' ').substring(0, 120),
      followers: countFields.followers(u),

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Log in to Instagram in the CLI session so endpoints return JSON instead of login HTML
  2. Capture and print response.text() for the failing request to see what Instagram actually returned
  3. Check response.ok/status before parsing JSON to distinguish HTTP errors from parse errors
  4. Retry after a short delay if it was a transient 5xx; disable interfering proxies

Example fix

// before
async function readInstagramJson(response, label) {
  try { return await response.json(); }
  catch { throw new Error(label + ' returned invalid JSON'); }
}
// after: include a body preview for diagnosis
async function readInstagramJson(response, label) {
  const text = await response.text();
  try { return JSON.parse(text); }
  catch { throw new Error(label + ' returned invalid JSON: ' + text.slice(0, 200)); }
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-flight: confirm the session cookie exists so endpoints return JSON, not login HTML
const cookies = await page.evaluate(`document.cookie`);
if (!cookies || !cookies.includes('sessionid')) {
  throw new Error('Not logged in to Instagram; run the login command first');
}

Type guard

function isJsonObject(text) {
  try { const v = JSON.parse(text); return v !== null && typeof v === 'object'; } catch { return false; }
}

Try / catch

try {
  const profile = await instagramProfile(username);
} catch (e) {
  if (/returned invalid JSON/.test(e.message)) {
    // usually a login/challenge HTML page — re-authenticate and retry once
    await instagramLogin();
    return instagramProfile(username);
  }
  throw e;
}

Prevention

When it happens

Trigger: An Instagram profile API endpoint returns non-JSON (login redirect HTML, challenge page, empty 200 body, or 5xx HTML error) during clis/instagram/profile.

Common situations: Expired/absent session causing Instagram to return the login HTML page with 200; Instagram serving a challenge/captcha page; proxy or captive portal injecting HTML; transient 5xx with HTML body.

Understand the failure class

Background: "Invalid JSON response" and "Failed to parse response" errors: when an API answers 200 but the body isn't the JSON your library expected — this error's family across 28 libraries.

Related errors


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