{"record":{"id":"c68a0aa4ef467994","repo":"jackwener/OpenCLI","slug":"could-not-attach-topic-topic-page-presskey-i","errorCode":null,"errorMessage":"Could not attach topic \"${topic}\": page.pressKey is unavailable","messagePattern":"Could not attach topic \"(.+?)\": page\\.pressKey is unavailable","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/xiaohongshu/publish.js","lineNumber":606,"sourceCode":"        // `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');\n        }\n        catch (err) {\n            throw new CommandExecutionError(`Could not attach topic \"${topic}\": failed to accept suggestion (${err && err.message || err})`);\n        }\n        await page.wait({ time: 0.8 });\n        // Verify the topic chip actually rendered. The chip itself lives in a\n        // closed shadow root so we cannot count `<a>` elements, but XHS exposes\n        // a stable \"#<topic>[话题]\" marker in the body editor's innerText once\n        // the suggestion is accepted. Require the scoped marker count to\n        // increase so an existing marker elsewhere cannot satisfy the write\n        // postcondition.\n        const afterMarkerCount = Number(unwrapBrowserResult(await page.evaluate(topicMarkerCountScript(topic, bodySelectors)))) || 0;\n        if (afterMarkerCount <= beforeMarkerCount) {\n            throw new CommandExecutionError(`Could not attach topic \"${topic}\": no real topic entity appeared after selection`);\n        }","sourceCodeStart":588,"sourceCodeEnd":624,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/xiaohongshu/publish.js#L588-L624","documentation":"CommandExecutionError guard in addTopics: after typing '#<topic>' the flow presses Enter to accept XHS's auto-highlighted first suggestion, but page.pressKey is not a function on the current page object. Since there is no reliable alternative wired into every wrapper, it throws with per-topic context.","triggerScenarios":"Browser-bridge wrapper without a pressKey implementation; older/patched driver versions; custom page shims exposing only legacy keyboard APIs.","commonSituations":"Using an alternative automation backend or outdated opencli bridge; environments where keyboard event dispatch is stubbed; running with a wrapper built for a different CLI version.","solutions":["Upgrade the CLI/browser bridge so page.pressKey is available.","Use the officially supported browser wrapper rather than a custom page object.","Publish without topics (remove the topics option) if your bridge cannot support them.","Pre-flight check: assert typeof page.pressKey === 'function' before a topics publish."],"exampleFix":"// before\nawait xhs.publish({ topics: ['travel'], ... }); // bridge lacks pressKey\n// after\nif (typeof page.pressKey !== 'function') delete opts.topics; // degrade gracefully\nawait xhs.publish(opts);","handlingStrategy":"type-guard","validationCode":"// pre-flight before a topics publish\nif (opts.topics && typeof page.pressKey !== 'function') {\n  throw new Error('Bridge lacks pressKey; publish without topics or upgrade');\n}","typeGuard":"function supportsKeyboard(page) {\n  return typeof page.pressKey === 'function';\n}","tryCatchPattern":"try {\n  await xhs.publish(opts);\n} catch (err) {\n  if (err.message.includes('page.pressKey is unavailable')) {\n    console.error('Use a bridge with pressKey support or omit topics');\n  } else throw err;\n}","preventionTips":["Feature-detect page.pressKey before publishing with topics","Keep the browser bridge at the supported version","Fall back to publishing without topics on limited bridges","Avoid custom page shims that strip keyboard APIs"],"tags":["automation","keyboard-events","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"}