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
- Log in to Instagram in the CLI session so endpoints return JSON instead of login HTML
- Capture and print response.text() for the failing request to see what Instagram actually returned
- Check response.ok/status before parsing JSON to distinguish HTTP errors from parse errors
- 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
- Always verify sessionid cookie presence before running profile queries
- Check response content-type/status before parsing JSON
- Avoid running through proxies that can inject HTML error pages
- Retry 5xx responses after a delay rather than parsing their HTML bodies
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.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Instagram whoami failed: ${result.detail}
- returned invalid JSON
- returned invalid JSON
- ${label} returned malformed JSON: ${err?.message ?? err}
- Xiaoyuzhou refresh returned invalid JSON: ${getErrorMessage(
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/51e5604b507da5f9.
Report an issue: GitHub.