jackwener/OpenCLI · error · CommandExecutionError
Failed to delete draft ${row.id}
Error message
Failed to delete draft ${row.id} What it means
Thrown by draft-delete.js when the in-page deleteDraftScript returns ok:false or no result, meaning the IndexedDB delete operation itself failed. The CLI falls back to a generic 'Failed to delete draft <id>' message when the script did not provide a more specific error.
Source
Thrown at clis/xiaohongshu/draft-delete.js:91
const draftType = normalizeDraftType(kwargs.type);
const execute = kwargs.execute === true;
await ensureDraftDbPage(page);
const entries = await readDraftEntries(page, draftType);
const entry = findDraftEntry(entries, id);
if (!entry) throw draftNotFound(id, draftType, 'xiaohongshu/draft-delete');
const row = normalizeDraftRecord(entry.row, entry.key, draftType, 1);
if (!execute) {
return [{
status: 'dry-run',
id: row.id,
type: draftType,
message: 'Draft exists. Re-run with --execute to delete.',
}];
}
const storeName = STORE_NAME_MAP[draftType];
const result = unwrapBrowserResult(await page.evaluate(deleteDraftScript(storeName, entry.key)));
if (!result?.ok) {
throw new CommandExecutionError(result?.error || `Failed to delete draft ${row.id}`);
}
if (!result.deleted) {
throw new CommandExecutionError(`Draft ${row.id} still exists after delete`);
}
return [{
status: 'deleted',
id: row.id,
type: draftType,
message: 'Draft deleted.',
}];
},
});
View on GitHub (pinned to 49907e53dc)
Solutions
- Re-run without --execute to confirm the draft still exists and get a fresh entry.key
- Refresh/reconnect the browser page (ensureDraftDbPage) and retry the delete
- Verify STORE_NAME_MAP for the chosen draftType matches the current XHS IndexedDB schema
- If result.error is present in other code paths, inspect it; here the message hides it, so add logging or update the library
Example fix
// before
const result = unwrapBrowserResult(await page.evaluate(deleteDraftScript(storeName, entry.key)));
// after
if (!entry.key) throw new ArgumentError('Draft key missing; re-run lookup without --execute');
const result = unwrapBrowserResult(await page.evaluate(deleteDraftScript(storeName, entry.key))); Defensive patterns
Strategy: try-catch
Validate before calling
const entry = await lookupDraft(page, draftType, id); // dry-run: fetches entry.key
if (!entry?.key) throw new Error(`Draft ${id} not found; nothing to delete`); Type guard
function isDeleteResult(r) {
return r != null && typeof r === 'object' && r.ok === true && typeof r.deleted === 'boolean';
} Try / catch
try {
await draftDelete({ type: 'video', id, execute: true });
} catch (e) {
if (/Failed to delete draft/.test(e.message)) {
console.error('Delete transaction failed — refresh the page/session and retry');
} else throw e;
} Prevention
- Always run the dry-run lookup immediately before --execute so entry.key is fresh
- Keep the target browser page alive and un-navigated during the command
- Verify STORE_NAME_MAP matches the live IndexedDB schema after XHS updates
- Handle the 'still exists after delete' follow-up error by re-fetching the key
When it happens
Trigger: Calling the delete command with --execute when page.evaluate(deleteDraftScript(...)) returns undefined/null or { ok: false } — e.g. the IndexedDB transaction failed, the store is missing, or the browser page was closed or navigated mid-operation.
Common situations: Draft already deleted in the UI so the record/key is stale; browser page navigated away or crashed during the evaluate; XHS updated its database schema so STORE_NAME_MAP points at a nonexistent store.
Related errors
- Draft ${row.id} still exists after delete
- Failed to ${execute ? 'clear' : 'count'} ${draftType} drafts
- ${result.after} ${draftType} drafts still exist after clear
- Not a git repository
- Working tree not clean: ${status}
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/24bf589a7f88100e.
Report an issue: GitHub.