{"record":{"id":"58d0b40dc16f0794","repo":"xpzouying/xiaohongshu-mcp","slug":"no-placeholder-element-found","errorCode":null,"errorMessage":"no placeholder element found","messagePattern":"no placeholder element found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"xiaohongshu/publish.go","lineNumber":769,"sourceCode":"\t\treturn errors.Wrap(err, \"点击标签联想选项失败\")\n\t}\n\tslog.Info(\"成功点击标签联想选项\", \"tag\", tag)\n\ttime.Sleep(500 * time.Millisecond) // 技术等待：等标签处理完成\n\treturn nil\n}\n\nfunc findTextboxByPlaceholder(page *rod.Page) (*rod.Element, error) {\n\telements, err := page.Elements(\"p\")\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"查找正文候选元素失败\")\n\t}\n\tif len(elements) == 0 {\n\t\treturn nil, errors.New(\"no p elements found\")\n\t}\n\n\tplaceholderElem := findPlaceholderElement(elements, \"输入正文描述\")\n\tif placeholderElem == nil {\n\t\treturn nil, errors.New(\"no placeholder element found\")\n\t}\n\n\ttextboxElem := findTextboxParent(placeholderElem)\n\tif textboxElem == nil {\n\t\treturn nil, errors.New(\"no textbox parent found\")\n\t}\n\n\treturn textboxElem, nil\n}\n\nfunc findPlaceholderElement(elements []*rod.Element, searchText string) *rod.Element {\n\tfor _, elem := range elements {\n\t\tplaceholder, err := elem.Attribute(\"data-placeholder\")\n\t\tif err != nil || placeholder == nil {\n\t\t\tcontinue\n\t\t}\n\n\t\tif strings.Contains(*placeholder, searchText) && isElementVisible(elem) {","sourceCodeStart":751,"sourceCodeEnd":787,"githubUrl":"https://github.com/xpzouying/xiaohongshu-mcp/blob/332d196854a9eac0d2b8c2c0e3d0cc43139d724c/xiaohongshu/publish.go#L751-L787","documentation":"After collecting `<p>` elements, findTextboxByPlaceholder scans their text for the placeholder '输入正文描述'. If no p element contains that text it throws 'no placeholder element found'. The description editor either hasn't rendered its placeholder yet, the placeholder text changed, or the user already typed content so the placeholder is gone.","triggerScenarios":"findContentElement → findTextboxByPlaceholder with searchText='输入正文描述'; the placeholder p exists with different wording (XHS copy update), or content was previously entered (placeholder hidden), or placeholder lives in a different element type (span/div data-placeholder attribute).","commonSituations":"XHS changing the placeholder copy (e.g. to '填写标题下更全面的描述信息'); re-running the flow on a page where content was already partially filled; locale/variant differences in placeholder text.","solutions":["Inspect the live page's editor DOM and update the placeholder searchText constant to the current copy","Match more loosely (substring or [placeholder]/[data-placeholder] attribute) instead of exact text","Only run this on a fresh publish page — if content was already typed, the placeholder disappears by design","Add the new placeholder text as an additional accepted value rather than replacing it, to tolerate A/B copy"],"exampleFix":"// before\nplaceholderElem := findPlaceholderElement(elements, \"输入正文描述\")\n// after\nplaceholderElem := findPlaceholderElement(elements, \"输入正文描述\")\nif placeholderElem == nil {\n\tplaceholderElem = findPlaceholderElement(elements, \"填写更全面的描述信息\") // 新版文案兜底\n}","handlingStrategy":"fallback","validationCode":"// 填写前确认正文为空（placeholder 只在空内容时存在）\nif contentAlreadyFilled(page) {\n\treturn errors.New(\"正文已填写，无需再定位 placeholder\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep a list of known placeholder texts (XHS changes copy across versions) and match any of them","Prefer matching placeholder attributes ([placeholder]/[data-placeholder]) over exact innerText","Run the flow on a fresh publish page; re-runs hide the placeholder once content exists"],"tags":["dom","placeholder","selector-drift","xiaohongshu"],"backgroundTag":"placeholder-element-not-found","analyzedSha":"332d196854a9eac0d2b8c2c0e3d0cc43139d724c","analyzedAt":"2026-09-05T22:22:55.988Z","contentChangedAt":"2026-09-05T22:22:55.988Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}