jackwener/OpenCLI · error · CommandExecutionError
xiaohongshu/delete-note: note ${noteId} still visible after
Error message
xiaohongshu/delete-note: note ${noteId} still visible after confirm click; deletion may not have committed. What it means
After clicking 确定, the CLI polls (1s interval, up to 10s) for the note row to disappear from the Published list; the row's disappearance is the proof the delete actually committed server-side. If the row is still present when polling exhausts, the CLI throws this CommandExecutionError warning that the deletion may not have committed — the confirm click happened but the state never changed.
Source
Thrown at clis/xiaohongshu/delete-note.js:240
if (!confirmResult?.ok) {
throw new CommandExecutionError(`xiaohongshu/delete-note: confirmation modal step failed (${confirmResult?.kind ?? 'unknown'})`);
}
// Step 4: poll for row removal (proves the delete actually committed,
// not just the modal was clicked). Iteration-bounded rather than
// wall-clock so tests with a mocked `page.wait` exhaust the loop
// quickly instead of stalling on real time.
const VERIFY_ITERATIONS = Math.ceil(VERIFY_TIMEOUT_MS / VERIFY_POLL_MS);
let stillPresent = true;
for (let i = 0; i < VERIFY_ITERATIONS; i++) {
await page.wait({ time: VERIFY_POLL_MS / 1000 });
const probe = requireEvaluateBoolean(unwrapEvaluateResult(await page.evaluate(buildVerifyGoneScript(noteId))), 'verify-gone');
if (probe === false) {
stillPresent = false;
break;
}
}
if (stillPresent) {
throw new CommandExecutionError(`xiaohongshu/delete-note: note ${noteId} still visible after confirm click; deletion may not have committed.`);
}
return [{ status: 'deleted', note_id: noteId, message: 'Delete confirmed and note row disappeared.' }];
}
catch (err) {
if (err instanceof CliError)
throw err;
throw new CommandExecutionError(`xiaohongshu/delete-note failed: ${err?.message ?? String(err)}`);
}
},
});
export const __test__ = {
normalizeNoteId,
buildLocateAndMaybeDeleteScript,
buildVerifyGoneScript,
};
View on GitHub (pinned to 49907e53dc)
Solutions
- Check creator.xiaohongshu.com in the browser: if the note is actually gone, the deletion succeeded and only the verification poll was too short (increase VERIFY_TIMEOUT_MS)
- If the note still exists, re-run the delete-note command from the start
- Retry after a short delay if XHS was slow; check for rate limiting or error toasts during the flow
- Re-login to creator.xiaohongshu.com if the session token expired mid-flow, then retry
Defensive patterns
Strategy: try-catch
Try / catch
try {
await cli('xiaohongshu', 'delete-note', { note: noteId });
} catch (err) {
if (err instanceof CommandExecutionError && err.message.includes('still visible after confirm click')) {
// Confirm was clicked — verify actual state before retrying to avoid double-delete
const stillThere = await noteStillListed(noteId);
if (stillThere) console.error('Deletion did not commit; safe to re-run the command.');
return;
}
throw err;
} Prevention
- Verify the note's actual state in the browser before re-running — the confirm click already happened and deletion may have committed slowly
- Avoid tight retry loops; XHS backend deletes can lag beyond the 10s verify window
- Watch for rate limiting; space out bulk deletions
- Ensure the session is healthy (re-login if auth tokens expired mid-flow) so the confirm request isn't silently rejected
When it happens
Trigger: The confirm click didn't actually submit the delete (silent frontend error or failed API call); server-side deletion is slower than the 10s verify window; the row remains in the DOM because the list re-fetch lagged; an API error toast appeared but the script only polls the row list; rate limiting or moderation state blocking deletion.
Common situations: XHS backend latency over 10 seconds during peak times; the modal confirm triggering a failed request (network hiccup, auth token expired mid-flow); the row cached in the list UI; the account hitting delete rate limits.
Related errors
- ${verb} could not be verified: no success marker or post-sub
- Unexpected 12306 probe: ${JSON.stringify(probe)}
- ChatGPT did not create a conversation URL after sending the
- ChatWise response
- Could not switch to ${wantModel} model
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/8403d77f58d31700.
Report an issue: GitHub.