xpzouying/xiaohongshu-mcp · error
no placeholder element found
Error message
no placeholder element found
What it means
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.
Source
Thrown at xiaohongshu/publish.go:769
return errors.Wrap(err, "点击标签联想选项失败")
}
slog.Info("成功点击标签联想选项", "tag", tag)
time.Sleep(500 * time.Millisecond) // 技术等待:等标签处理完成
return nil
}
func findTextboxByPlaceholder(page *rod.Page) (*rod.Element, error) {
elements, err := page.Elements("p")
if err != nil {
return nil, errors.Wrap(err, "查找正文候选元素失败")
}
if len(elements) == 0 {
return nil, errors.New("no p elements found")
}
placeholderElem := findPlaceholderElement(elements, "输入正文描述")
if placeholderElem == nil {
return nil, errors.New("no placeholder element found")
}
textboxElem := findTextboxParent(placeholderElem)
if textboxElem == nil {
return nil, errors.New("no textbox parent found")
}
return textboxElem, nil
}
func findPlaceholderElement(elements []*rod.Element, searchText string) *rod.Element {
for _, elem := range elements {
placeholder, err := elem.Attribute("data-placeholder")
if err != nil || placeholder == nil {
continue
}
if strings.Contains(*placeholder, searchText) && isElementVisible(elem) {View on GitHub (pinned to 332d196854)
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
Example fix
// before
placeholderElem := findPlaceholderElement(elements, "输入正文描述")
// after
placeholderElem := findPlaceholderElement(elements, "输入正文描述")
if placeholderElem == nil {
placeholderElem = findPlaceholderElement(elements, "填写更全面的描述信息") // 新版文案兜底
} Defensive patterns
Strategy: fallback
Validate before calling
// 填写前确认正文为空(placeholder 只在空内容时存在)
if contentAlreadyFilled(page) {
return errors.New("正文已填写,无需再定位 placeholder")
} Prevention
- 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
When it happens
Trigger: 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).
Common situations: 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.
Related errors
AI-assisted analysis of xpzouying/xiaohongshu-mcp@332d196854 (2026-09-05).
Data as JSON: /api/errors/58d0b40dc16f0794.
Report an issue: GitHub.