jackwener/OpenCLI · error · Error
returned malformed post row
Error message
returned malformed post row
What it means
After locating the feed item, the CLI extracts the post id (post.pk ?? post.id), normalizes it to a numeric string, and requires it to be all digits. A non-matching pk means the feed row is not a normal media post (e.g. an ad, story bundle, or reshaped item), so it throws '${label} returned malformed post row'.
Source
Thrown at clis/instagram/comment.js:43
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');
return { pk };
}
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');
const { pk } = getPostFromFeed(await readInstagramJson(r1, 'Instagram feed-by-username'), 'Instagram feed-by-username');
const csrf = document.cookie.match(/csrftoken=([^;]+)/)?.[1] || '';
const r2 = await fetch('https://www.instagram.com/api/v1/web/comments/' + pk + '/add/', {
method: 'POST', credentials: 'include',
headers: { ...headers, 'X-CSRFToken': csrf, 'Content-Type': 'application/x-www-form-urlencoded' },
body: 'comment_text=' + encodeURIComponent(commentText),View on GitHub (pinned to 49907e53dc)
Solutions
- Skip that index and pick a different post, or filter non-media items (ads, announcements) from items first
- Log the offending item and update pk extraction to read the new nesting (e.g. post.media.pk)
- Retry with a fresh session if the item shape differs due to experiment buckets
- Post-process pk by stripping non-digit characters only if the id is a known formatted variant
Example fix
// before const pkRaw = post?.pk ?? post?.id; const pk = typeof pkRaw === 'number' ? String(pkRaw) : (typeof pkRaw === 'string' ? pkRaw.trim() : ''); // after const pkRaw = post?.pk ?? post?.id ?? post?.media?.pk; const pk = String(pkRaw ?? '').replace(/\D/g, ''); if (!pk) throw new Error(label + ' returned malformed post row: ' + JSON.stringify(post).slice(0, 200));
Defensive patterns
Strategy: type-guard
Validate before calling
const post = feed.items[idx];
const pkRaw = post?.pk ?? post?.id ?? post?.media?.pk;
const pk = String(pkRaw ?? '').replace(/\D/g, '');
if (!/^\d+$/.test(pk)) console.warn('Non-media item at index, skip'); Type guard
function hasNumericPk(post) {
const raw = post?.pk ?? post?.id;
return typeof raw === 'number' || (typeof raw === 'string' && /^\d+$/.test(raw.trim()));
} Try / catch
try {
await runCommentPipeline(args);
} catch (e) {
if (/malformed post row/.test(e.message)) {
console.warn('Feed item is not a normal media post (ad/wrapper) - try another index');
} else throw e;
} Prevention
- Filter ads/promoted items from feed items
- Prefer indexes on recent organic posts
- Log the offending item to track schema changes
- Normalize pk/id defensively before use
When it happens
Trigger: The selected feed item is an ad, IGTV/clip wrapper, carousel metadata, or otherwise lacks a numeric pk/id; Instagram schema changes move pk into a nested field.
Common situations: Commenting on accounts whose feeds include promoted posts at the chosen index; new media types (e.g. trial reels) that carry string-with-suffix ids; partial API migrations returning nested objects.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Instagram post feed returned malformed payload for ${usernam
- Instagram post feed returned no valid owner id for ${usernam
- Instagram post feed returned malformed post row for ${userna
- ${label} returned malformed items payload
- Instagram following returned malformed user row
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/79bfd30e4d3bfbba.
Report an issue: GitHub.