jackwener/OpenCLI · error

returned malformed items payload

Error message

 returned malformed items payload

What it means

Thrown by `getPostFromFeed` when the parsed feed-by-username response is valid JSON but lacks the expected shape: no `feed`, not an object, or `feed.items` is not an array. The CLI relies on `items` being the post array; any other shape means Instagram's API response changed or a non-feed payload (e.g. an error object with status 200) was returned.

Source

Thrown at clis/instagram/save.js:35

    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');
    }
  }

  // web_profile_info answers HTTP 400 for business accounts; feed-by-username needs no user id. See #2234.
  const r1 = await fetch('https://www.instagram.com/api/v1/feed/user/' + encodeURIComponent(username) + '/username/?count=' + (idx + 1), opts);
  if (!r1.ok) throw new Error(r1.status === 404 ? 'User not found: ' + username : 'HTTP ' + r1.status + ' - make sure you are logged in to Instagram');

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Log the raw response body once to see what Instagram actually returned, then confirm whether it is an error envelope or schema change.
  2. Refresh the Instagram login session in the CLI's browser profile — a 200 error envelope often means the session is stale.
  3. Retry later if it is a bot-detection/limiting payload; avoid rapid repeated invocations.
  4. Update the CLI (or the hardcoded `feed.items` parsing) if Instagram changed its API schema.
Defensive patterns

Strategy: type-guard

Type guard

function isFeedPayload(x) {
  return x !== null && typeof x === 'object' && Array.isArray(x.items);
}

Try / catch

try {
  await run(['instagram', 'save', username, '--index', String(i)]);
} catch (e) {
  if (String(e.message).includes('returned malformed items payload')) {
    // API returned an unexpected envelope: refresh session and retry once,
    // otherwise flag for CLI/schema update
    await refreshInstagramLogin();
    return retryOnce();
  }
  throw e;
}

Prevention

When it happens

Trigger: GET /api/v1/feed/user/<username>/username/ returns HTTP 200 with JSON that is not a feed object: an `{"message": ...}` error envelope, a `{"status": "fail"}` object, `items: null`, or Instagram shipping a schema change that renames/moves the `items` array.

Common situations: Instagram silently degrades a request with a 200 + error JSON (e.g. login required payload); the target account is private/deleted so the payload has no items; Instagram rolls out an API schema change that breaks the hardcoded shape; a bot-detection payload replaces the feed data.

Understand the failure class

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/ea24d2ba5b5488fe. Report an issue: GitHub.