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
- Log into Instagram in the browser profile the CLI drives and retry.
- Retry later if rate-limited; reduce request frequency.
- 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
- Ensure an active Instagram login in the browser profile
- Detect login-page HTML responses early
- Reduce request frequency to avoid challenge pages
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.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- returned invalid JSON
- Instagram whoami failed: ${result.detail}
- Failed to fetch followers: HTTP ' + r2.status
- ${label} returned invalid JSON
- User not found: ' + username : 'HTTP ' + r1.status + ' - mak
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/b9ddbae097a57f62.
Report an issue: GitHub.