jackwener/OpenCLI · error

${label} returned invalid JSON

Error message

${label} returned invalid JSON

What it means

readInstagramJson wraps response.json(); when the response body cannot be parsed as JSON it rethrows '${label} returned invalid JSON'. This catches Instagram returning HTML (login pages, challenge pages) or empty bodies instead of the expected JSON API payload.

Source

Thrown at clis/instagram/comment.js:32

        },
        { name: 'text', required: true, positional: true, help: 'Comment text' },
        { name: 'index', type: 'int', default: 1, help: 'Post index (1 = most recent)' },
    ],
    columns: ['status', 'user', 'text'],
    pipeline: [
        { navigate: 'https://www.instagram.com' },
        { evaluate: `(async () => {
  const username = \${{ args.username | json }};
  const commentText = \${{ args.text | json }};
  const idx = \${{ args.index }} - 1;
  if (!Number.isInteger(idx) || idx < 0) throw new Error('index must be a positive integer');
  const headers = { 'X-IG-App-ID': '936619743392459' };
  const opts = { credentials: 'include', headers };
  async function readInstagramJson(response, label) {
    try {
      return await response.json();
    } catch {
      throw new Error(label + ' returned invalid JSON');
    }
  }
  function getPostFromFeed(feed, label) {
    if (!feed || typeof feed !== 'object' || !Array.isArray(feed.items)) {
      throw new Error(label + ' returned malformed items payload');
    }
    if (idx >= feed.items.length) throw new Error('Post index ' + (idx + 1) + ' not found');
    const post = feed.items[idx];
    const pkRaw = post?.pk ?? post?.id;
    const pk = typeof pkRaw === 'number' ? String(pkRaw) : (typeof pkRaw === 'string' ? pkRaw.trim() : '');
    if (!/^\\d+$/.test(pk)) throw new Error(label + ' returned malformed post row');
    return { pk };
  }
  function assertOkStatus(payload, label) {
    if (!payload || typeof payload !== 'object' || payload.status !== 'ok') {
      throw new Error(label + ' returned no success evidence');
    }
  }

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Re-authenticate / refresh Instagram session cookies so responses are API JSON, not login HTML
  2. Check the raw response text and Content-Type; if HTML, a login or challenge is being served
  3. Retry after backoff if the failure is transient (rate limiting/outage)
  4. Confirm the request path/headers (X-IG-App-ID, credentials: 'include') are intact

Example fix

// before
async function readInstagramJson(response, label) {
  try { return await response.json(); }
  catch { throw new Error(label + ' returned invalid JSON'); }
}
// after
async function readInstagramJson(response, label) {
  const text = await response.text();
  try { return JSON.parse(text); }
  catch {
    if (/login|challenge/i.test(text.slice(0, 500))) throw new Error(label + ': session expired, re-login required');
    throw new Error(label + ' returned invalid JSON: ' + text.slice(0, 200));
  }
}
Defensive patterns

Strategy: try-catch

Validate before calling

const res = await fetch(url, opts);
const ct = res.headers.get('content-type') || '';
if (!ct.includes('application/json')) {
  throw new Error('Expected JSON, got ' + ct + ' - session probably expired');
}

Type guard

function isJsonResponse(res) {
  return (res.headers.get('content-type') || '').includes('application/json');
}

Try / catch

try {
  await runCommentPipeline(args);
} catch (e) {
  if (/returned invalid JSON/.test(e.message)) {
    console.error('Instagram returned non-JSON (login/challenge page) - refresh cookies');
  } else throw e;
}

Prevention

When it happens

Trigger: A fetch (feed-by-username or comment add) resolves ok but the body is HTML — e.g. a login redirect page, consent/challenge interstitial, rate-limit HTML, or an empty 204-style response passed to res.json().

Common situations: Expired session cookies so IG serves the login page; account flagged for verification showing a challenge page; HTML error pages served during outages or heavy rate limiting.

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/8383cc09007f1676. Report an issue: GitHub.