jackwener/OpenCLI · error
' + label + ' returned no success evidence
Error message
' + label + ' returned no success evidence
What it means
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.
Source
Thrown at clis/instagram/unsave.js:47
} 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');
const { pk, caption } = 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/save/' + pk + '/unsave/', {
method: 'POST', credentials: 'include',
headers: { ...headers, 'X-CSRFToken': csrf, 'Content-Type': 'application/x-www-form-urlencoded' },
});
if (!r2.ok) throw new Error('Failed to unsave: HTTP ' + r2.status);
assertOkStatus(await readInstagramJson(r2, 'Instagram unsave'), 'Instagram unsave');
return [{ status: 'Unsaved', user: username, post: caption || '(post #' + (idx+1) + ')' }];
})()
` },View on GitHub (pinned to 49907e53dc)
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.
Defensive patterns
Strategy: retry
Validate before calling
const csrf = document.cookie.match(/csrftoken=([^;]+)/)?.[1];
if (!csrf) throw new Error('Missing csrftoken — log in first'); Type guard
const saveOk = (d) => !!d && typeof d === 'object' && d.status === 'ok';
Try / catch
try {
await cli.unsave(user, index);
} catch (e) {
if (e.message.includes('no success evidence')) {
await delay(2000);
await cli.unsave(user, index); // retry once after session refresh
} else throw e;
} Prevention
- Refresh csrftoken before mutation calls
- Avoid unsaving the same post twice in one run
- Space out mutation requests
When it happens
Trigger: 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.
Common situations: Stale csrftoken cookie; running unsave twice on the same post; Instagram silently rejecting automation.
Related errors
- Instagram private route could not derive CSRF token from bro
- returned no success evidence
- Failed to save: HTTP ' + r2.status
- Failed to unfollow: HTTP ' + r2.status
- Instagram unfollow returned no success evidence
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/a4bbf1c56818b980.
Report an issue: GitHub.