jackwener/OpenCLI · error · CommandExecutionError
Failed to remove @${username} from list ${listId}: member_co
Error message
Failed to remove @${username} from list ${listId}: member_count unchanged (${memberCountBefore} → ${memberCountAfter}). What it means
The library found the target list in the post-delete payload and compared member counts: the count did not decrease (equal or higher), meaning the Save click did not actually remove the user. The removal failed silently in the UI, so the library throws instead of reporting success.
Source
Thrown at clis/twitter/list-remove-core.js:257
if (!r.ok) return { __error: 'HTTP ' + r.status };
return await r.json();
}`));
if (listsAfter && listsAfter.__error) {
throw new CommandExecutionError(`Could not verify list removal: ${listsAfter.__error}`);
}
if (!getListsManagementInstructions(listsAfter)) {
throw new CommandExecutionError('Could not verify list removal: unexpected lists payload shape');
}
const parsedAfter = parseListsManagement(listsAfter, new Set());
const afterList = parsedAfter.find((l) => l.id === listId);
if (!afterList) {
throw new CommandExecutionError(`Could not verify list removal: list ${listId} missing from post-delete payload`);
}
const memberCountAfter = Number(afterList.members) || 0;
if (memberCountAfter < memberCountBefore) {
verifiedBy = `member_count ${memberCountBefore} → ${memberCountAfter}`;
} else {
throw new CommandExecutionError(`Failed to remove @${username} from list ${listId}: member_count unchanged (${memberCountBefore} → ${memberCountAfter}).`);
}
}
return [{
listId,
username,
userId: String(userId),
status: uiResult.noop ? 'noop' : 'success',
message: uiResult.noop
? `@${username} was not a member of list ${listId}`
: `Removed @${username} from list ${listId} (verified via ${verifiedBy})`,
}];
}
View on GitHub (pinned to 49907e53dc)
Solutions
- Simply retry the command — most of these are transient timing races; the next run re-scrapes fresh coordinates
- Slow things down / use a machine with less load, and avoid scrolling or interacting with the browser during the 800ms/3500ms waits
- Check whether the target user is still a member with `opencli twitter lists` / list members; remove manually if the UI keeps failing
- Update the Chrome extension and opencli — older nativeClick versions can drop synthesized clicks
- If persistent, the toggle likely opened the profile: report the coordinate-click flow as broken for the current X DOM
Example fix
// before
await listRemoveUser(page, { listId, username });
// after
let done = false;
for (let i = 0; i < 2 && !done; i++) {
try { await listRemoveUser(page, { listId, username }); done = true; }
catch (e) {
if (!/member_count unchanged/.test(e.message)) throw e;
await new Promise(r => setTimeout(r, 5000));
}
}
if (!done) console.error('Removal failed twice; check list membership manually.'); Defensive patterns
Strategy: retry
Validate before calling
const lists = await run('twitter', 'lists', {});
const target = lists.find(l => String(l.id) === String(listId));
if (!target) throw new Error(`List ${listId} not found.`);
const before = Number(target.members) || 0;
// capture before-count so you can detect unchanged state yourself Try / catch
for (let attempt = 0; attempt < 2; attempt++) {
try { await listRemoveUser(page, { listId, username }); break; }
catch (e) {
if (!/member_count unchanged/.test(e.message) || attempt === 1) throw e;
await new Promise(r => setTimeout(r, 5000));
}
} Prevention
- Don't interact with the browser during the click sequence (800ms/3500ms waits are timing-sensitive)
- Retry once automatically — races are usually transient
- Keep the extension and library current (nativeClick reliability)
- After failures, check actual membership via the lists/members API instead of assuming either way
When it happens
Trigger: nativeClick on the row toggled membership but the Save click was missed/mis-timed (3500ms wait hit a still-saving dialog), or the row click opened the user profile instead of toggling, so the member_count after equals the count before.
Common situations: Slow rendering so the second click landed before the toggle registered; the coordinates drifted because the dialog scrolled or re-laid out between scrape and click; the extension's nativeClick was intercepted by an X overlay (toast, tooltip); rate-limited actions accepted by UI but rejected server-side.
Related errors
- Failed to confirm add-to-cart success.
- settings click failed
- sidebar-toggle failed
- 无法在聊天列表中找到该用户,候选人可能不在当前列表中
- 找不到消息输入框
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/5fa435d95c1b5cd5.
Report an issue: GitHub.