xpzouying/xiaohongshu-mcp · error
no textbox parent found
Error message
no textbox parent found
What it means
Once the placeholder <p> is located, findTextboxByPlaceholder climbs ancestors via findTextboxParent to find the actual editable container ([contenteditable] or equivalent). If no ancestor qualifies, it throws 'no textbox parent found'. The placeholder text node exists but its editable wrapper isn't recognized by the current ancestor checks — typically due to an XHS editor DOM restructure.
Source
Thrown at xiaohongshu/publish.go:774
}
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) {
return elem
}
}
return nil
}View on GitHub (pinned to 332d196854)
Solutions
- Inspect the current editor DOM and extend findTextboxParent's matching rules (e.g. also accept elements with class like 'ql-editor' or role=textbox)
- Increase traversal depth if the contenteditable ancestor is higher than the current limit
- Verify the placeholder <p> you matched is inside the real editor, not a template/hidden copy
- If matching stays brittle, locate the editor directly via a stable wrapper selector instead of climbing from the placeholder
Example fix
// before
textboxElem := findTextboxParent(placeholderElem)
// after
textboxElem := findTextboxParent(placeholderElem)
if textboxElem == nil {
// 兜底:直接按编辑器容器选择器找
if el, err := page.Element("[contenteditable='true']"); err == nil {
textboxElem = el
}
} Defensive patterns
Strategy: fallback
Validate before calling
// 直接探测编辑器容器是否可定位
if _, err := page.Element("[contenteditable='true'], .ql-editor"); err != nil {
return errors.New("未找到可编辑正文容器")
} Prevention
- Prefer locating the editor by a stable wrapper selector over ancestor-climbing from the placeholder
- Re-check findTextboxParent's accepted patterns after XHS editor upgrades
- Verify the matched placeholder <p> is inside the real editor, not a hidden template
When it happens
Trigger: findContentElement → findTextboxByPlaceholder; placeholder <p> found but findTextboxParent never encounters a [contenteditable]/editable ancestor within its traversal depth because XHS wrapped the editor in new elements or moved contenteditable to a shadow/iframe boundary.
Common situations: XHS editor upgrade changing nesting depth or moving contenteditable off the ancestor chain; placeholder rendered inside a tooltip/overlay layer rather than the editor itself; proxy/injected wrapper elements altering ancestry.
Related errors
AI-assisted analysis of xpzouying/xiaohongshu-mcp@332d196854 (2026-09-05).
Data as JSON: /api/errors/a8d18930134ae643.
Report an issue: GitHub.