jackwener/OpenCLI · error · CommandExecutionError
Could not attach topic "${topic}": body editor not found
Error message
Could not attach topic "${topic}": body editor not found What it means
CommandExecutionError from addTopics: before attaching a topic the code calls focusBodyEnd to place the caret at the end of the note body editor; if it cannot find/focus the editor it aborts rather than typing '#' into the void. Thrown per-topic at the start of each topic iteration.
Source
Thrown at clis/xiaohongshu/publish.js:576
catch {
// fall through to execCommand path
}
}
return unwrapBrowserResult(await page.evaluate(`
(text => {
const ok = document.execCommand('insertText', false, text);
const active = document.activeElement;
if (active) active.dispatchEvent(new Event('input', { bubbles: true }));
return ok;
})(${JSON.stringify(query)})
`));
}
async function addTopics(page, bodySelectors, topics) {
const added = [];
for (const topic of topics) {
const focused = await focusBodyEnd(page, bodySelectors);
if (!focused) {
throw new CommandExecutionError(`Could not attach topic "${topic}": body editor not found`);
}
const beforeMarkerCount = Number(unwrapBrowserResult(await page.evaluate(topicMarkerCountScript(topic, bodySelectors)))) || 0;
// Separate this topic from the preceding text so the dropdown is clean.
if (typeof page.pressKey === 'function') {
try {
await page.pressKey('Enter');
}
catch { /* non-fatal */ }
}
// Type the inline "#<topic>" query so XHS pops the inline suggestion
// dropdown. We must use `page.insertText` (CDP) rather than the legacy
// `execCommand` path, otherwise XHS's editor doesn't fire its keyup
// listener and no dropdown appears.
if (typeof page.insertText !== 'function') {
throw new CommandExecutionError(`Could not attach topic "${topic}": page.insertText is unavailable`);
}
try {
await page.insertText(`#${topic}`);View on GitHub (pinned to 49907e53dc)
Solutions
- Verify the session is logged in and the publish page shows the body editor.
- Add delays/waits so the editor fully renders before topics are attached.
- Update the CLI to get refreshed body selectors.
- Use the debug screenshots from earlier fill failures to identify page-state problems.
Example fix
// before
await xhs.publish({ topics: ['travel'], images: [...] });
// after
await xhs.publish({ topics: ['travel'], images: [...], wait: 8 }); // give editor time to mount
// or wrap: try { ... } catch (e) { if (e.message.includes('body editor not found')) retryAfterDelay(); } Defensive patterns
Strategy: retry
Validate before calling
// ensure logged-in publisher page loads before topic attach
if ((await page.url()).includes('login')) throw new Error('session expired'); Try / catch
try {
await xhs.publish(opts);
} catch (err) {
if (err.message.includes('body editor not found')) {
await sleep(8000); // let editor mount
return retryPublish(opts);
}
throw err;
} Prevention
- Verify the body editor renders before adding topics
- Keep sessions logged in
- Add wait time for slow environments
- Update CLI for selector refreshes after XHS redesigns
When it happens
Trigger: Body editor selector list no longer matches the XHS editor DOM; editor not yet mounted when addTopics runs; page navigated or showing a login/verification wall; editor inside a shadow root the focus logic cannot reach after an update.
Common situations: XHS redesign of the creator editor; publishing without a valid session so the editor never renders; timing issues on slow machines/networks.
Related errors
- Could not find ${fieldName} input. Debug screenshot: /tmp/xh
- Instagram reel caption editor did not appear
- Failed to fill title
- Failed to fill author
- Failed to fill summary
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/9a5cdea412d88e50.
Report an issue: GitHub.