{"record":{"id":"aa42af4c0bc497ad","repo":"jackwener/OpenCLI","slug":"label-returned-malformed-post-row","errorCode":null,"errorMessage":"' + label + ' returned malformed post row","messagePattern":"' \\+ label \\+ ' returned malformed post row","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"clis/instagram/unsave.js","lineNumber":41,"sourceCode":"  if (!Number.isInteger(idx) || idx < 0) throw new Error('index must be a positive integer');\n  const headers = { 'X-IG-App-ID': '936619743392459' };\n  const opts = { credentials: 'include', headers };\n  async function readInstagramJson(response, label) {\n    try {\n      return await response.json();\n    } catch {\n      throw new Error(label + ' returned invalid JSON');\n    }\n  }\n  function getPostFromFeed(feed, label) {\n    if (!feed || typeof feed !== 'object' || !Array.isArray(feed.items)) {\n      throw new Error(label + ' returned malformed items payload');\n    }\n    if (idx >= feed.items.length) throw new Error('Post index ' + (idx + 1) + ' not found');\n    const post = feed.items[idx];\n    const pkRaw = post?.pk ?? post?.id;\n    const pk = typeof pkRaw === 'number' ? String(pkRaw) : (typeof pkRaw === 'string' ? pkRaw.trim() : '');\n    if (!/^\\\\d+$/.test(pk)) throw new Error(label + ' returned malformed post row');\n    const caption = typeof post?.caption?.text === 'string' ? post.caption.text.substring(0, 60) : '';\n    return { pk, caption };\n  }\n  function assertOkStatus(payload, label) {\n    if (!payload || typeof payload !== 'object' || payload.status !== 'ok') {\n      throw new Error(label + ' returned no success evidence');\n    }\n  }\n\n  // web_profile_info answers HTTP 400 for business accounts; feed-by-username needs no user id. See #2234.\n  const r1 = await fetch('https://www.instagram.com/api/v1/feed/user/' + encodeURIComponent(username) + '/username/?count=' + (idx + 1), opts);\n  if (!r1.ok) throw new Error(r1.status === 404 ? 'User not found: ' + username : 'HTTP ' + r1.status + ' - make sure you are logged in to Instagram');\n  const { pk, caption } = getPostFromFeed(await readInstagramJson(r1, 'Instagram feed-by-username'), 'Instagram feed-by-username');\n\n  const csrf = document.cookie.match(/csrftoken=([^;]+)/)?.[1] || '';\n  const r2 = await fetch('https://www.instagram.com/api/v1/web/save/' + pk + '/unsave/', {\n    method: 'POST', credentials: 'include',\n    headers: { ...headers, 'X-CSRFToken': csrf, 'Content-Type': 'application/x-www-form-urlencoded' },","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/instagram/unsave.js#L23-L59","documentation":"The matched feed item did not contain a usable post id: neither pk nor id was present, or the value failed the /^\\d+$/ numeric-string check. The CLI cannot build the unsave URL without a valid post primary key.","triggerScenarios":"feed item is an ad, story, or non-media row lacking pk/id, or Instagram returns a different id field for that media type.","commonSituations":"Targeting an index that points to a promoted/ad item in the feed; new Instagram media types with different id shapes; API shape drift.","solutions":["Try a different --index pointing at a normal post.","Inspect the feed item to find where the id now lives and update the CLI.","Skip ads/stories rows when computing the index."],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":"const hasPk = (post) => /^\\d+$/.test(String(post?.pk ?? post?.id ?? ''));","typeGuard":"function hasValidPostId(post) {\n  const pk = post?.pk ?? post?.id;\n  return typeof pk !== 'undefined' && /^\\d+$/.test(String(pk));\n}","tryCatchPattern":null,"preventionTips":["Skip ad/story feed rows when computing indices","Keep the CLI updated for new Instagram media id shapes","Log the offending item when the guard trips"],"tags":["instagram","api-response","schema-mismatch"],"backgroundTag":"schema-validation-failed","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}