{"record":{"id":"4cb58941a551f57a","repo":"xpzouying/xiaohongshu-mcp","slug":"error-4cb589","errorCode":null,"errorMessage":"输入#失败","messagePattern":"输入#失败","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"xiaohongshu/publish.go","lineNumber":727,"sourceCode":"\tif err := ka.Press(input.Enter).Press(input.Enter).Do(); err != nil {\n\t\treturn errors.Wrap(err, \"按下回车键失败\")\n\t}\n\n\ttime.Sleep(1 * time.Second)\n\n\tfor _, tag := range tags {\n\t\ttag = strings.TrimLeft(tag, \"#\")\n\t\tif err := inputTag(ctx, contentElem, tag); err != nil {\n\t\t\treturn errors.Wrapf(err, \"输入标签[%s]失败\", tag)\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc inputTag(ctx context.Context, contentElem *rod.Element, tag string) error {\n\t// 输入 # 触发话题联想\n\tif err := humanize.Type(ctx, contentElem, \"#\"); err != nil {\n\t\treturn errors.Wrap(err, \"输入#失败\")\n\t}\n\ttime.Sleep(200 * time.Millisecond) // 技术等待：等联想下拉框弹出\n\n\tif err := humanize.Type(ctx, contentElem, tag); err != nil {\n\t\treturn errors.Wrap(err, \"输入标签内容失败\")\n\t}\n\n\ttime.Sleep(1 * time.Second) // 技术等待：等联想结果刷新\n\n\tpage := contentElem.Page()\n\ttopicContainer, err := page.Element(\"#creator-editor-topic-container\")\n\tif err != nil || topicContainer == nil {\n\t\tslog.Warn(\"未找到标签联想下拉框，直接输入空格\", \"tag\", tag)\n\t\treturn humanize.Type(ctx, contentElem, \" \")\n\t}\n\n\tfirstItem, err := topicContainer.Element(\".item\")\n\tif err != nil || firstItem == nil {","sourceCodeStart":709,"sourceCodeEnd":745,"githubUrl":"https://github.com/xpzouying/xiaohongshu-mcp/blob/332d196854a9eac0d2b8c2c0e3d0cc43139d724c/xiaohongshu/publish.go#L709-L745","documentation":"inputTag wraps any failure from humanize.Type when typing the '#' character into the content editor element. The '#' keystroke is required to trigger Xiaohongshu's topic-autocomplete dropdown; if the underlying browser automation typing fails, the error is wrapped as 输入#失败. It means the browser could not reliably send the '#' key to the content <p> element.","triggerScenarios":"Calling inputTags with a tag list when the content element has become stale/detached, the page navigated away, the editor lost focus, or the rod browser connection dropped during humanize.Type of '#'.","commonSituations":"Slow page load so the editor isn't ready when tags are typed; page re-render replaces the content element mid-typing; browser tab crashed or was closed; network latency to a remote CDP browser exceeding rod's timeouts.","solutions":["Ensure the publish page and editor are fully loaded before calling inputTags (wait for the content element to be visible/stable).","Re-acquire the content element right before typing instead of reusing a cached *rod.Element.","Increase the rod/browser CDP timeout or check network stability to the browser endpoint.","Retry the tag input once after a short sleep; the UI may have been momentarily busy."],"exampleFix":"// before\ntagErr := inputTags(ctx, contentElem, tags)\n// after\nif err := contentElem.WaitStable(300 * time.Millisecond); err != nil {\n    return errors.Wrap(err, \"content element not stable\")\n}\ntagErr := inputTags(ctx, contentElem, tags)","handlingStrategy":"retry","validationCode":"if err := contentElem.WaitStable(300 * time.Millisecond); err != nil { return errors.Wrap(err, \"编辑器不可用\") }","typeGuard":"func isTypingErr(err error) bool { return err != nil && strings.Contains(err.Error(), \"输入#失败\") }","tryCatchPattern":"for i := 0; i < 2; i++ {\n    if err := inputTag(ctx, contentElem, tag); err == nil { break }\n    time.Sleep(500 * time.Millisecond)\n}","preventionTips":["Always wait for the editor element to be stable before typing tags","Re-acquire the element after page transitions","Monitor CDP connection health for remote browsers"],"tags":["browser-automation","rod","xhs-publish"],"backgroundTag":"cdp-element-typing-failed","analyzedSha":"332d196854a9eac0d2b8c2c0e3d0cc43139d724c","analyzedAt":"2026-09-05T22:22:55.988Z","contentChangedAt":"2026-09-05T22:22:55.988Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}