jackwener/OpenCLI · error · CommandExecutionError

xiaohongshu/delete-note: note ${noteId} row found but no del

Error message

xiaohongshu/delete-note: note ${noteId} row found but no delete action visible; xhs creator UI may have changed.

What it means

The note row was located, but the injected script could not find a visible delete action (the inline `<span class="control data-del">` or equivalent hover control) on that row. The CLI raises CommandExecutionError because deletion cannot proceed without the action; this usually means XHS changed the row-action markup or the control is rendered under a state the script doesn't handle.

Source

Thrown at clis/xiaohongshu/delete-note.js:201

        return false;
      }
    `)), 'published-tab');
            if (!tabClicked) {
                throw new CommandExecutionError('xiaohongshu/delete-note: 已发布 tab not found on note-manager; xhs creator UI may have changed.');
            }
            await page.wait({ time: ROW_SETTLE_MS / 1000 });
            // Step 2: locate the .note row whose data-impression JSON carries the
            // exact `noteId` field. Dry-run stops here; execute clicks delete.
            // Substring matching on the raw attribute would risk matching unrelated
            // fields whose values happen to share the noteId prefix, so parse the JSON
            // and compare `noteTarget.value.noteId` explicitly.
            const initResult = requireActionResult(unwrapEvaluateResult(await page.evaluate(buildLocateAndMaybeDeleteScript(noteId, execute))), 'locate-note');
            if (!initResult?.ok) {
                if (initResult?.kind === 'not_found') {
                    throw new EmptyResultError('xiaohongshu/delete-note', `Note ${noteId} not visible in the 已发布 tab. Verify the note belongs to the logged-in account and has cleared review (审核中 / 未通过 rows have no web delete entry).`);
                }
                if (initResult?.kind === 'no_delete_action') {
                    throw new CommandExecutionError(`xiaohongshu/delete-note: note ${noteId} row found but no delete action visible; xhs creator UI may have changed.`);
                }
                throw new CommandExecutionError('xiaohongshu/delete-note: failed to locate note row');
            }
            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 };

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Re-run the command (hover-state timing can be transient); try a wider/maximized browser window so inline actions render
  2. Inspect the row in DevTools to see whether the delete control still exists; if markup changed, update the library/selector logic
  3. Update the opencli package to the latest version that tracks the current XHS UI
  4. If no web delete entry truly exists for this note state, delete via the XHS mobile app instead
Defensive patterns

Strategy: retry

Validate before calling

// Pre-check the row exposes a delete control before invoking:
const hasDelete = await page.evaluate(`(id) => {
  for (const row of document.querySelectorAll('.note')) {
    try {
      const j = JSON.parse(row.getAttribute('data-impression') || '');
      if (j?.noteTarget?.value?.noteId === id) {
        return !!row.querySelector('.control.data-del');
      }
    } catch {}
  }
  return false;
}`, noteId);
if (!hasDelete) throw new Error('delete action not visible on row');

Try / catch

try {
  await cli('xiaohongshu', 'delete-note', { note: noteId });
} catch (err) {
  if (err instanceof CommandExecutionError && err.message.includes('no delete action visible')) {
    await sleep(2000); // hover/settle then retry once
    return cli('xiaohongshu', 'delete-note', { note: noteId });
  }
  throw err;
}

Prevention

When it happens

Trigger: XHS renamed/removed the .control.data-del element or changed its visibility conditions (e.g. requiring hover first in a new way); a UI variant renders actions differently; the row is in a state where no delete action exists despite being on the Published tab; element considered invisible (offsetParent null) due to layout changes.

Common situations: XHS frontend update changing action-button markup; per-account A/B layouts; browser window too narrow so action buttons collapse into an overflow menu; CSS changes making the control invisible to the offsetParent check.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/7e4fea06ed9c0b04. Report an issue: GitHub.