{"record":{"id":"1f5165f210050f0d","repo":"jackwener/OpenCLI","slug":"failed-to-fill-content","errorCode":null,"errorMessage":"Failed to fill content","messagePattern":"Failed to fill content","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/weixin/create-draft.js","lineNumber":304,"sourceCode":"        { name: 'cover-image', help: '封面图片路径 (会先上传到正文再设为封面)' },\n        { name: 'summary', help: '文章摘要' },\n        { name: 'timeout', type: 'int', required: false, default: 180, help: 'Max seconds for the overall command (default: 180)' },\n    ],\n    columns: ['status', 'detail'],\n\n    func: async (page, kwargs) => {\n        try {\n            const coverImage = kwargs['cover-image'] ? resolveCoverImage(kwargs['cover-image']) : null;\n            await navigateToEditor(page);\n\n            const titleResult = await fillField(page, 'textarea#title', kwargs.title);\n            if (!titleResult?.ok) throw new CommandExecutionError('Failed to fill title');\n            if (kwargs.author) {\n                const authorResult = await fillField(page, 'input#author', kwargs.author);\n                if (!authorResult?.ok) throw new CommandExecutionError('Failed to fill author');\n            }\n            const contentResult = await fillContent(page, kwargs.content);\n            if (!contentResult?.ok) throw new CommandExecutionError('Failed to fill content');\n\n            if (coverImage) {\n                await uploadContentImage(page, coverImage);\n                const coverSet = await selectCoverFromContent(page);\n                if (coverSet !== true) {\n                    throw new CommandExecutionError('WeChat uploaded the image but did not confirm it as the draft cover.');\n                }\n            }\n\n            if (kwargs.summary) {\n                const summaryResult = await fillField(page, 'textarea#js_description', kwargs.summary);\n                if (!summaryResult?.ok) throw new CommandExecutionError('Failed to fill summary');\n            }\n\n            await saveDraft(page);\n            return [{\n                status: 'draft saved',\n                detail: `\"${kwargs.title}\"${kwargs.author ? ` by ${kwargs.author}` : ''}${coverImage ? ' (with cover)' : ''}`,","sourceCodeStart":286,"sourceCodeEnd":322,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/weixin/create-draft.js#L286-L322","documentation":"This CommandExecutionError is thrown when fillContent() fails to insert the article body. fillContent queries div[contenteditable=\"true\"] elements and picks the last one; if none exists it returns {ok:false, reason:'content editor not found'}, which the command surfaces as this error. It means the rich-text contenteditable editor was absent when the content step ran.","triggerScenarios":"Calling create-draft when no div[contenteditable=\"true\"] element is present in the editor DOM: the UEditor rich-text iframe/instance has not initialized within the fixed 4-second wait, WeChat changed the editor implementation (no longer a contenteditable div), or the page served is a degraded/variant editor.","commonSituations":"UEditor initializes asynchronously and slowly on first load or large accounts, so the contenteditable node is not yet attached; WeChat rolls out a new editor (e.g., a ProseMirror-based one) removing the contenteditable div; heavy content in kwargs.content times out execCommand-based insertion indirectly by racing page state; proxy or slow network delays page load.","solutions":["Retry — UEditor async initialization past the fixed 4s wait is the most common cause.","Inspect the live editor and confirm a div[contenteditable=\"true\"] exists; update fillContent()'s selector strategy in clis/weixin/create-draft.js if WeChat changed the editor.","Wait explicitly for the contenteditable editor (or #ueditor_0) to appear before calling fillContent.","Check whether content contains characters that break the JSON.stringify-injected execCommand('insertText') path; test with plain ASCII content to isolate."],"exampleFix":"// before\nconst contentResult = await fillContent(page, kwargs.content);\nif (!contentResult?.ok) throw new CommandExecutionError('Failed to fill content');\n// after\nawait page.waitForSelector('div[contenteditable=\"true\"]', { timeout: 15000 });\nconst contentResult = await fillContent(page, kwargs.content);\nif (!contentResult?.ok) throw new CommandExecutionError('Failed to fill content: ' + (contentResult?.reason ?? 'unknown'));","handlingStrategy":"validation","validationCode":"const editorReady = await page.evaluate('document.querySelectorAll(\"div[contenteditable=true]\").length > 0');\nif (editorReady !== true) throw new Error('Content editor not initialized; wait or re-navigate before filling content.');","typeGuard":null,"tryCatchPattern":"try {\n  await createDraft({ title, content });\n} catch (e) {\n  if (e instanceof CommandExecutionError && /Failed to fill content/.test(e.message)) {\n    // retry after a longer delay (UEditor async init), or fail fast with a clear message\n  } else throw e;\n}","preventionTips":["Keep article content free of characters that could break the injected script; test with plain text first.","Allow extra initial load time on first run of the day or on large accounts (UEditor initializes slowly).","Verify the contenteditable editor still exists in the DOM after WeChat editor updates.","Prefer an explicit wait-for-selector over fixed sleeps in any local modification."],"tags":["puppeteer","contenteditable","wechat","automation"],"backgroundTag":"dom-element-not-found","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}