{"record":{"id":"9a5cdea412d88e50","repo":"jackwener/OpenCLI","slug":"could-not-attach-topic-topic-body-editor-not","errorCode":null,"errorMessage":"Could not attach topic \"${topic}\": body editor not found","messagePattern":"Could not attach topic \"(.+?)\": body editor not found","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/xiaohongshu/publish.js","lineNumber":576,"sourceCode":"        catch {\n            // fall through to execCommand path\n        }\n    }\n    return unwrapBrowserResult(await page.evaluate(`\n    (text => {\n      const ok = document.execCommand('insertText', false, text);\n      const active = document.activeElement;\n      if (active) active.dispatchEvent(new Event('input', { bubbles: true }));\n      return ok;\n    })(${JSON.stringify(query)})\n  `));\n}\nasync function addTopics(page, bodySelectors, topics) {\n    const added = [];\n    for (const topic of topics) {\n        const focused = await focusBodyEnd(page, bodySelectors);\n        if (!focused) {\n            throw new CommandExecutionError(`Could not attach topic \"${topic}\": body editor not found`);\n        }\n        const beforeMarkerCount = Number(unwrapBrowserResult(await page.evaluate(topicMarkerCountScript(topic, bodySelectors)))) || 0;\n        // Separate this topic from the preceding text so the dropdown is clean.\n        if (typeof page.pressKey === 'function') {\n            try {\n                await page.pressKey('Enter');\n            }\n            catch { /* non-fatal */ }\n        }\n        // Type the inline \"#<topic>\" query so XHS pops the inline suggestion\n        // dropdown. We must use `page.insertText` (CDP) rather than the legacy\n        // `execCommand` path, otherwise XHS's editor doesn't fire its keyup\n        // listener and no dropdown appears.\n        if (typeof page.insertText !== 'function') {\n            throw new CommandExecutionError(`Could not attach topic \"${topic}\": page.insertText is unavailable`);\n        }\n        try {\n            await page.insertText(`#${topic}`);","sourceCodeStart":558,"sourceCodeEnd":594,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/xiaohongshu/publish.js#L558-L594","documentation":"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.","triggerScenarios":"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.","commonSituations":"XHS redesign of the creator editor; publishing without a valid session so the editor never renders; timing issues on slow machines/networks.","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."],"exampleFix":"// before\nawait xhs.publish({ topics: ['travel'], images: [...] });\n// after\nawait xhs.publish({ topics: ['travel'], images: [...], wait: 8 }); // give editor time to mount\n// or wrap: try { ... } catch (e) { if (e.message.includes('body editor not found')) retryAfterDelay(); }","handlingStrategy":"retry","validationCode":"// ensure logged-in publisher page loads before topic attach\nif ((await page.url()).includes('login')) throw new Error('session expired');","typeGuard":null,"tryCatchPattern":"try {\n  await xhs.publish(opts);\n} catch (err) {\n  if (err.message.includes('body editor not found')) {\n    await sleep(8000); // let editor mount\n    return retryPublish(opts);\n  }\n  throw err;\n}","preventionTips":["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"],"tags":["automation","dom-selector","topics","xiaohongshu"],"backgroundTag":"selector-not-found","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}