jackwener/OpenCLI · error

returned invalid JSON

Error message

 returned invalid JSON

What it means

One of the Instagram HTTP responses could not be parsed as JSON (response.json() threw inside readInstagramJson). The failing call is identified by the label prefix. Usually the endpoint returned HTML (login page, challenge, or error page) instead of JSON.

Source

Thrown at clis/instagram/unsave.js:30

            positional: true,
            help: 'Username of the post author',
        },
        { name: 'index', type: 'int', default: 1, help: 'Post index (1 = most recent)' },
    ],
    columns: ['status', 'user', 'post'],
    pipeline: [
        { navigate: 'https://www.instagram.com' },
        { evaluate: `(async () => {
  const username = \${{ args.username | 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');
    const caption = typeof post?.caption?.text === 'string' ? post.caption.text.substring(0, 60) : '';
    return { pk, caption };
  }
  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. Log into Instagram in the browser profile the CLI drives and retry.
  2. Retry later if rate-limited; reduce request frequency.
  3. Check the response manually (curl with cookies) to confirm what body is returned.

Example fix

// before
const data = await r1.json();
// after
let data;
try { data = await r1.json(); }
catch { throw new Error('Instagram feed-by-username returned invalid JSON — check login session'); }
Defensive patterns

Strategy: try-catch

Validate before calling

if (!document.cookie.includes('sessionid')) throw new Error('Not logged into Instagram');

Try / catch

try {
  await cli.unsave(user, index);
} catch (e) {
  if (e.message.includes('invalid JSON')) {
    console.error('Non-JSON response — likely logged out. Re-authenticate and retry.');
  } else throw e;
}

Prevention

When it happens

Trigger: feed-by-username or unsave endpoint returns non-JSON body — login redirect HTML, rate-limit page, or Cloudflare challenge — while HTTP status may still be 200.

Common situations: Expired session causing Instagram to return the login page with status 200; logged out of the browser profile; Instagram serving an interstitial for automated traffic.

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