jackwener/OpenCLI · error · CommandExecutionError
xiaohongshu/delete-note: failed to locate note row
Error message
xiaohongshu/delete-note: failed to locate note row
What it means
Generic fallback for the locate step: the injected script returned { ok: false } with a kind that was neither 'not_found' nor 'no_delete_action' (or the result shape was unexpected beyond the boolean check). The CLI throws this CommandExecutionError because it cannot classify the locate failure.
Source
Thrown at clis/xiaohongshu/delete-note.js:203
`)), '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 };
}
`)), 'confirm-modal');View on GitHub (pinned to 49907e53dc)
Solutions
- Re-run the command; transient rendering races often resolve on retry
- Ensure the opencli package (and clis/xiaohongshu files) are all the same version — no partial upgrades
- Load the note-manager page in the browser first to confirm it renders normally before running the command
- If reproducible, file/inspect with the actual initResult payload to identify the unhandled kind and update the classification logic
Defensive patterns
Strategy: retry
Try / catch
try {
await cli('xiaohongshu', 'delete-note', { note: noteId });
} catch (err) {
if (err instanceof CommandExecutionError && err.message.includes('failed to locate note row')) {
await sleep(3000); // transient render/execution race — retry once
return cli('xiaohongshu', 'delete-note', { note: noteId });
}
throw err;
} Prevention
- Retry transient locate failures once before escalating
- Keep all related packages on one version to avoid script/result kind mismatches
- Load and settle the note-manager page before running the delete command
- Capture the raw initResult payload when debugging to identify unclassified failure kinds
When it happens
Trigger: The injected locate script returned an unexpected failure kind (e.g. an exception path inside the page context, a new kind added by a mismatched script/result version); the page was navigated or the execution context destroyed mid-evaluate; partial rendering left rows in an inconsistent state.
Common situations: Version skew between the injected script builder and the result parser after a partial library update; XHS JS throwing during row scan so the script exits early with an unclassified status; SPA re-render racing the evaluate call.
Related errors
- Midjourney did not expose "${config.label}" for video ${jobI
- Failed to remove @${username} from list ${listId}: ${uiResul
- xiaohongshu/delete-note: 已发布 tab not found on note-manager;
- Note ${noteId} not visible in the 已发布 tab. Verify the note b
- xiaohongshu/delete-note: note ${noteId} row found but no del
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/03b1849b63ec90a7.
Report an issue: GitHub.