jackwener/OpenCLI · error · CommandExecutionError
xiaohongshu/delete-note: confirmation modal step failed (${c
Error message
xiaohongshu/delete-note: confirmation modal step failed (${confirmResult?.kind ?? 'unknown'}) What it means
Step 3 clicks 确定 (Confirm) in the .d-modal-footer confirmation modal after clicking delete. The script reported ok:false with a kind (e.g. 'no_modal', 'no_confirm') or an unknown shape, so the CLI throws this CommandExecutionError naming the failing kind. The delete was initiated but never confirmed, so nothing was deleted.
Source
Thrown at clis/xiaohongshu/delete-note.js:223
if (!execute) {
return [{ status: 'dry-run', note_id: noteId, message: 'Target note row and delete action verified. Re-run with --execute to delete.' }];
}
await page.wait({ time: MODAL_SETTLE_MS / 1000 });
// Step 3: click "确定" in the `.d-modal-footer` confirmation modal.
const confirmResult = requireActionResult(unwrapEvaluateResult(await page.evaluate(`
() => {
const isVisible = (el) => !!el && el.offsetParent !== null;
const footer = Array.from(document.querySelectorAll('.d-modal-footer')).find(isVisible);
if (!footer) return { ok: false, kind: 'no_modal' };
const buttons = Array.from(footer.querySelectorAll('button, [role="button"]')).filter(isVisible);
const confirmBtn = buttons.find((b) => (b.innerText || b.textContent || '').trim() === '确定');
if (!confirmBtn) return { ok: false, kind: 'no_confirm', labels: buttons.map(b => (b.innerText || '').trim()) };
confirmBtn.click();
return { ok: true };
}
`)), 'confirm-modal');
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.`);
}View on GitHub (pinned to 49907e53dc)
Solutions
- Re-run the command; if the modal was just slow, a retry may succeed (consider increasing MODAL_SETTLE_MS if configurable)
- Inspect the confirm modal in DevTools: if .d-modal-footer or the 确定 button markup changed, update the selector logic in the library
- Update the opencli package to the latest version tracking the current XHS UI
- Maximize the browser window / reset zoom so the modal renders normally
- IMPORTANT: because the delete was initiated but not confirmed, verify in the browser whether the note still exists before retrying to avoid double-delete attempts
Defensive patterns
Strategy: retry
Try / catch
try {
await cli('xiaohongshu', 'delete-note', { note: noteId });
} catch (err) {
if (err instanceof CommandExecutionError && err.message.includes('confirmation modal step failed')) {
// Deletion was initiated but NOT confirmed — verify current state before retrying
const stillThere = await noteStillListed(noteId);
if (stillThere) return cli('xiaohongshu', 'delete-note', { note: noteId });
return; // already deleted
}
throw err;
} Prevention
- Always re-check whether the note still exists before retrying — the delete click already fired
- Maximize the window / reset zoom so the confirm modal renders normally
- Retry with a longer settle delay if the modal is slow to appear
- Keep opencli updated for XHS modal markup (.d-modal-footer / 确定) changes
When it happens
Trigger: The confirmation modal did not appear within MODAL_SETTLE_MS (2s); XHS changed the modal markup (.d-modal-footer class removed/renamed) so no confirm button is found; the confirm button label no longer matches 确定; the modal rendered but buttons were invisible to the offsetParent check.
Common situations: Slow rendering past the 2s modal settle window; XHS frontend update altering modal classes; browser window/zoom making the modal render off-layout; a different dialog variant (A/B test) with different button markup.
Related errors
- xiaohongshu/delete-note: 已发布 tab not found on note-manager;
- xiaohongshu/delete-note: note ${noteId} row found but no del
- settings click failed
- sidebar-toggle failed
- 无法在聊天列表中找到该用户,候选人可能不在当前列表中
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/66770f84ea668f2f.
Report an issue: GitHub.