{"record":{"id":"b4413a09085476c3","repo":"jackwener/OpenCLI","slug":"could-not-attach-topic-topic-page-inserttext","errorCode":null,"errorMessage":"Could not attach topic \"${topic}\": page.insertText is unavailable","messagePattern":"Could not attach topic \"(.+?)\": page\\.insertText is unavailable","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/xiaohongshu/publish.js","lineNumber":591,"sourceCode":"    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}`);\n        }\n        catch {\n            throw new CommandExecutionError(`Could not attach topic \"${topic}\": failed to type inline topic query`);\n        }\n        await page.wait({ time: 1.2 }); // Let the suggestion dropdown render.\n        // The suggestion dropdown lives inside the editor's closed shadow root,\n        // so light-DOM queries cannot enumerate its items. XHS auto-highlights\n        // the first matching suggestion as soon as the query is typed, so\n        // pressing Enter accepts it directly. `page.nativeClick` would also\n        // work but is not always wired up in the browser-bridge wrapper.\n        if (typeof page.pressKey !== 'function') {\n            throw new CommandExecutionError(`Could not attach topic \"${topic}\": page.pressKey is unavailable`);\n        }\n        try {\n            await page.pressKey('Enter');","sourceCodeStart":573,"sourceCodeEnd":609,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/xiaohongshu/publish.js#L573-L609","documentation":"CommandExecutionError guard in addTopics: typing the inline '#topic' query requires page.insertText (CDP Input.insertText) because legacy execCommand does not trigger XHS's keyup listener and no suggestion dropdown appears. If the browser-bridge wrapper lacks insertText, the topic cannot be attached reliably, so it throws instead of silently skipping.","triggerScenarios":"Using an older or alternative browser automation bridge whose page object does not expose insertText; a downgraded/patched wrapper (e.g. custom page shim) lacking CDP text insertion; wrong driver version.","commonSituations":"Mixing this CLI with a custom Puppeteer/Playwright-style page object; older opencli browser bridge versions; running in environments where CDP insertText is stubbed out.","solutions":["Upgrade the CLI / browser bridge so page.insertText is implemented (CDP Input.insertText).","Use the supported bundled browser wrapper instead of a custom page object.","Remove topics from the publish call if your environment cannot support them.","Check wrapper feature detection before publishing: typeof page.insertText === 'function'."],"exampleFix":"// before\nconst page = myCustomWrapper.connect();\nawait xhs.publish({ topics: ['travel'], ... }); // wrapper lacks insertText\n// after\nconst page = require('opencli').browser.connect(); // supported wrapper with CDP insertText\nawait xhs.publish({ topics: ['travel'], ... });","handlingStrategy":"type-guard","validationCode":"// feature-detect the bridge before publishing with topics\nif (opts.topics && typeof page.insertText !== 'function') {\n  console.warn('bridge lacks insertText; dropping topics');\n  delete opts.topics;\n}","typeGuard":"function supportsInlineTyping(page) {\n  return typeof page.insertText === 'function';\n}","tryCatchPattern":"try {\n  await xhs.publish(opts);\n} catch (err) {\n  if (err.message.includes('page.insertText is unavailable')) {\n    console.error('Upgrade the browser bridge to a CDP-capable version');\n  } else throw err;\n}","preventionTips":["Use the officially supported browser wrapper","Keep the CLI and bridge updated","Feature-detect page.insertText before topic publishes","Drop topics gracefully in environments without CDP"],"tags":["automation","cdp","api-compatibility","xiaohongshu"],"backgroundTag":"browser-api-missing","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}