jackwener/OpenCLI · error · CommandExecutionError
WeChat draft save was not confirmed by a fresh success statu
Error message
WeChat draft save was not confirmed by a fresh success status.
What it means
Thrown by saveDraft after the save-draft button was clicked but the 8-attempt confirmation loop (each with a 1-second wait) never observed a fresh save status via readSaveState — i.e. no visible status text appeared, or the text never changed from the pre-save snapshot. The library requires positive confirmation that the draft was saved.
Source
Thrown at clis/weixin/create-draft.js:270
async function saveDraft(page) {
const before = await readSaveState(page);
const result = await evaluate(page, `(() => {
var button = Array.from(document.querySelectorAll('span, button, a')).find(function(el) {
return (el.textContent || '').trim() === '保存为草稿' && !el.disabled;
});
if (!button) return { ok: false };
button.click();
return { ok: true };
})()`);
if (!result?.ok) throw new CommandExecutionError('WeChat save-draft button was not found.');
for (let attempt = 0; attempt < 8; attempt++) {
await page.wait(1);
const state = await readSaveState(page);
if (state?.visible && (!before?.visible || state.text !== before.text)) return;
}
throw new CommandExecutionError('WeChat draft save was not confirmed by a fresh success status.');
}
export const createDraftCommand = cli({
site: 'weixin',
name: 'create-draft',
access: 'write',
description: '创建微信公众号图文草稿',
domain: WEIXIN_DOMAIN,
strategy: Strategy.COOKIE,
browser: true,
navigateBefore: false,
args: [
{ name: 'title', required: true, help: '文章标题 (最长64字)' },
{ name: 'content', required: true, positional: true, help: '文章正文' },
{ name: 'author', help: '作者名 (最长8字)' },
{ name: 'cover-image', help: '封面图片路径 (会先上传到正文再设为封面)' },
{ name: 'summary', help: '文章摘要' },
{ name: 'timeout', type: 'int', required: false, default: 180, help: 'Max seconds for the overall command (default: 180)' },View on GitHub (pinned to 49907e53dc)
Solutions
- Retry the command; transient click or save failures often succeed on the second attempt.
- Increase the polling attempts/duration to accommodate slow saves.
- Check whether the status-text freshness comparison (state.text !== before.text) is too strict for repeat saves of an unchanged draft, and relax it or compare save timestamps.
- Confirm the status element selector in readSaveState still matches WeChat's current UI and update it if the editor changed.
Example fix
// before
if (state?.visible && (!before?.visible || state.text !== before.text)) return;
// after
if (state?.visible && (!before?.visible || state.text !== before.text || state.text.includes('成功'))) return; Defensive patterns
Strategy: retry
Validate before calling
const before = await readSaveState(page); // capture pre-save status
// ensure the save click happened; re-check button state
const clicked = await evaluate(page, 'Array.from(document.querySelectorAll("button, a")).some(el => (el.textContent || "").trim() === "保存为草稿")');
if (clicked !== true) throw new Error('save button gone; cannot confirm save'); Type guard
function isSaveState(v) { return typeof v === 'object' && v !== null && (typeof v.visible === 'boolean') && typeof v.text === 'string'; } Try / catch
try {
await createDraftCommand(opts);
} catch (e) {
if (/not confirmed by a fresh success status/i.test(e.message)) {
await sleep(5000);
return createDraftCommand(opts); // slow save — retry once
}
throw e;
} Prevention
- Allow longer polling for slow networks before treating save as failed.
- Verify no modal (e.g. confirm/unsaved-changes dialog) intercepts the save click.
- Re-check readSaveState's status element selector after WeChat UI updates.
- Verify the draft actually appeared in the MP draft list when this error fires repeatedly, to distinguish detection bugs from real save failures.
When it happens
Trigger: The click didn't register (overlay, animation), the save request failed server-side without changing the status text, the save finished but the status text was identical to the pre-save snapshot (before.text) so the freshness check never passed, or saving takes longer than the ~8-second polling window.
Common situations: Slow WeChat saves exceeding 8 seconds; editing an already-saved draft where the status text doesn't change; page modals (e.g. unsaved-changes prompts) swallowing the click; WeChat changing the status message element read by readSaveState.
Related errors
- 未检测到抖音草稿恢复提示
- twitter retweet confirmation
- twitter unblock confirmation
- twitter unbookmark confirmation
- twitter unfollow confirmation
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/cfd7a3690069e6f2.
Report an issue: GitHub.