jackwener/OpenCLI · error · CommandExecutionError

Instagram private publish ${stage} returned invalid JSON

Error message

Instagram private publish ${stage} returned invalid JSON

What it means

parseJsonResponse expects the Instagram API response body to be valid JSON; when the body is non-empty but unparseable it throws this error (clis/instagram/_shared/private-publish.js:751). It indicates the endpoint returned HTML, an empty-ish proxy error page, or some other non-JSON payload while the HTTP layer looked fine to fetch.

Source

Thrown at clis/instagram/_shared/private-publish.js:751

        'X-Entity-Length': String(asset.coverImage.byteLength),
        'X-Entity-Name': `fb_uploader_${uploadId}`,
        'X-Entity-Type': asset.coverImage.mimeType,
        'X-Instagram-Rupload-Params': JSON.stringify({
            media_type: 2,
            upload_id: uploadId,
            upload_media_height: asset.height,
            upload_media_width: asset.width,
        }),
    };
}
async function parseJsonResponse(response, stage) {
    const text = await response.text();
    let data;
    try {
        data = text ? JSON.parse(text) : {};
    }
    catch {
        throw new CommandExecutionError(`Instagram private publish ${stage} returned invalid JSON`);
    }
    if (!response.ok) {
        const detail = text ? ` ${text.slice(0, 500)}` : '';
        throw new CommandExecutionError(`Instagram private publish ${stage} failed: ${response.status}${detail}`);
    }
    return data;
}
async function fetchPrivateUploadWithRetry(fetcher, url, init) {
    let lastError;
    for (let attempt = 0; attempt < INSTAGRAM_PRIVATE_UPLOAD_RETRY_BUDGET; attempt += 1) {
        try {
            return await fetcher(url, init);
        }
        catch (error) {
            lastError = error;
            if (!isTransientPrivateFetchError(error) || attempt >= INSTAGRAM_PRIVATE_UPLOAD_RETRY_BUDGET - 1) {
                throw error;
            }

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Refresh or re-export your Instagram session cookies — the old session is likely being redirected to an HTML login page
  2. Log the raw response text (first ~500 chars) to see what the server actually returned
  3. Check for proxy/VPN interference and retry from a clean network
  4. Retry later — transient Instagram-side error pages often resolve

Example fix

// before
const data = await parseJsonResponse(response, 'upload');
// after
try { const data = await parseJsonResponse(response, 'upload'); }
catch (e) { if (/invalid JSON/.test(e.message)) console.error('server said:', (await response.text?.()) ?? e.detail); throw e; }
Defensive patterns

Strategy: retry

Validate before calling

null

Type guard

const isInvalidJsonError = (e) => e instanceof CommandExecutionError && /returned invalid JSON/.test(e.message);

Try / catch

try { return await publish(input); }
catch (e) {
  if (isInvalidJsonError(e)) {
    await sleep(5000);
    return publish(input); // retry once; if persistent, session is likely expired
  }
  throw e;
}

Prevention

When it happens

Trigger: Any private publish stage (upload, video upload, video cover upload, sidecar publish) where response.text() returns a non-JSON string that JSON.parse rejects — e.g. an HTML login page, a rate-limit page, or a CDN error body.

Common situations: Instagram serving an HTML challenge/login redirect because the session cookie expired; corporate proxies or captive portals returning HTML; hitting the wrong endpoint after an API change; response body compressed/mangled by an intermediary proxy.

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