{"record":{"id":"a4bbf1c56818b980","repo":"jackwener/OpenCLI","slug":"label-returned-no-success-evidence","errorCode":null,"errorMessage":"' + label + ' returned no success evidence","messagePattern":"' \\+ label \\+ ' returned no success evidence","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"clis/instagram/unsave.js","lineNumber":47,"sourceCode":"    } 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' },\n  });\n  if (!r2.ok) throw new Error('Failed to unsave: HTTP ' + r2.status);\n  assertOkStatus(await readInstagramJson(r2, 'Instagram unsave'), 'Instagram unsave');\n  return [{ status: 'Unsaved', user: username, post: caption || '(post #' + (idx+1) + ')' }];\n})()\n` },","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/instagram/unsave.js#L29-L65","documentation":"The unsave POST returned a body without status:'ok', so the CLI cannot confirm the post was unsaved. assertOkStatus enforces Instagram's success contract; any other body (error object, empty JSON) fails. HTTP status was 200 but the operation itself did not succeed.","triggerScenarios":"POST /api/v1/web/save/{pk}/unsave/ returns 200 with an error payload — missing/invalid CSRF token, post already unsaved, or session rejected server-side.","commonSituations":"Stale csrftoken cookie; running unsave twice on the same post; Instagram silently rejecting automation.","solutions":["Refresh the session and csrftoken cookie by logging in again in the browser profile.","Check whether the post was already unsaved; treat this as success then.","Retry after a delay to clear soft rate limits."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"const csrf = document.cookie.match(/csrftoken=([^;]+)/)?.[1];\nif (!csrf) throw new Error('Missing csrftoken — log in first');","typeGuard":"const saveOk = (d) => !!d && typeof d === 'object' && d.status === 'ok';","tryCatchPattern":"try {\n  await cli.unsave(user, index);\n} catch (e) {\n  if (e.message.includes('no success evidence')) {\n    await delay(2000);\n    await cli.unsave(user, index); // retry once after session refresh\n  } else throw e;\n}","preventionTips":["Refresh csrftoken before mutation calls","Avoid unsaving the same post twice in one run","Space out mutation requests"],"tags":["instagram","csrf","authentication","api-response"],"backgroundTag":"api-response-missing-success-status","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}