xpzouying/xiaohongshu-mcp · error
读取旧版发布按钮 class 属性失败
Error message
读取旧版发布按钮 class 属性失败
What it means
findPublishButton wraps the error from Element.Attribute("class") on a visible legacy publish button when the CDP read fails. As with the other attribute reads, this is a transport/element-lifecycle failure, not a 'button has disabled class' result. The library needs the class list to detect the disabled-styled variant, so it aborts the search.
Source
Thrown at xiaohongshu/publish.go:534
for _, oldButton := range oldButtons {
if !isElementVisible(oldButton) {
continue
}
if disabled, err := oldButton.Attribute("disabled"); err != nil {
return nil, "", errors.Wrap(err, "读取旧版发布按钮 disabled 属性失败")
} else if disabled != nil {
return &publishButton{elem: oldButton}, "旧版发布按钮 disabled", nil
}
if ariaDisabled, err := oldButton.Attribute("aria-disabled"); err != nil {
return nil, "", errors.Wrap(err, "读取旧版发布按钮 aria-disabled 属性失败")
} else if ariaDisabled != nil && *ariaDisabled == "true" {
return &publishButton{elem: oldButton}, "旧版发布按钮 aria-disabled=true", nil
}
if cls, err := oldButton.Attribute("class"); err != nil {
return nil, "", errors.Wrap(err, "读取旧版发布按钮 class 属性失败")
} else if cls != nil && hasExactClass(*cls, "disabled") {
return &publishButton{elem: oldButton}, "旧版发布按钮包含 disabled class", nil
}
return &publishButton{elem: oldButton}, "", nil
}
return nil, "", nil
}
func clickPublishWidget(page *rod.Page, widget *rod.Element) error {
if err := widget.ScrollIntoView(); err != nil {
return errors.Wrap(err, "滚动新版发布按钮到可视区域失败")
}
time.Sleep(200 * time.Millisecond)
shape, err := widget.Shape()
if err != nil {View on GitHub (pinned to 332d196854)
Solutions
- Retry the flow — findPublishButton is invoked inside a polling loop and will pick up fresh elements
- Wait for the DOM to settle (page.WaitDOMStable / WaitStable) before starting the publish-button wait
- Detect a dead browser/tab and re-launch or re-open the page instead of retrying against the stale handle
- Keep rod updated to pick up CDP race-condition fixes
Example fix
// before
for {
btn, reason, err := findPublishButton(page)
// after
for {
_ = page.WaitStable(300 * time.Millisecond)
btn, reason, err := findPublishButton(page) Defensive patterns
Strategy: retry
Validate before calling
if err := page.WaitStable(300 * time.Millisecond); err != nil { return err }
oldButtons, err := page.Elements(".publish-page-publish-btn button.bg-red")
if err != nil || len(oldButtons) == 0 { return errors.New("旧版发布按钮不可用") } Type guard
func elementAttached(page *rod.Page, sel string) bool {
els, err := page.Elements(sel)
return err == nil && len(els) > 0
} Try / catch
btn, reason, err := waitForPublishButtonClickable(page)
if err != nil && strings.Contains(err.Error(), "class 属性失败") {
time.Sleep(500 * time.Millisecond)
btn, reason, err = waitForPublishButtonClickable(page)
} Prevention
- Retry transient CDP attribute errors a fixed number of times before giving up
- Stabilize the page before classification so class mutations settle
- Detect closed targets (browser each/monitor) and re-open proactively
- Log the raw underlying error to distinguish detach vs connection failure
When it happens
Trigger: Element detached during the attribute-read sequence (after `disabled` and `aria-disabled` reads succeeded); page navigation/closed tab; CDP protocol error; browser OOM crash.
Common situations: Fast re-render of the publish button right as the check runs; flaky connection to a remote Chrome instance; script continuing to use a rod.Page after its window was closed.
Related errors
AI-assisted analysis of xpzouying/xiaohongshu-mcp@332d196854 (2026-09-05).
Data as JSON: /api/errors/4e4143d9060988a0.
Report an issue: GitHub.