xpzouying/xiaohongshu-mcp · error

读取旧版发布按钮 aria-disabled 属性失败

Error message

读取旧版发布按钮 aria-disabled 属性失败

What it means

Same family as the `disabled` read failure: findPublishButton wraps the error from Element.Attribute("aria-disabled") on a visible legacy publish button. The CDP attribute read itself failed — the button state is unknown, not aria-disabled. The library cannot proceed with its clickability classification, so it aborts.

Source

Thrown at xiaohongshu/publish.go:528

	oldButtons, err := page.Elements(".publish-page-publish-btn button.bg-red")
	if err != nil {
		return nil, "", errors.Wrap(err, "查找旧版发布按钮失败")
	}

	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 {

View on GitHub (pinned to 332d196854)

Solutions

  1. Retry the wait/click flow — the polling loop re-queries elements so a detached node is usually transient
  2. Add WaitDOMStable/WaitStable before invoking waitForPublishButtonClickable to avoid reading attributes mid-mutation
  3. Verify the Chrome target is still connected (check rod errors / re-launch browser on failure)
  4. Pin/upgrade the rod dependency; some Attribute races were fixed upstream

Example fix

// before
btn, reason, err := findPublishButton(page)
// after
_ = page.WaitStable(300 * time.Millisecond)
btn, reason, err := findPublishButton(page)
Defensive patterns

Strategy: retry

Validate before calling

if err := page.WaitDOMStable(time.Second, 0.1); err != nil { return err }
if _, err := page.Elements(".publish-page-publish-btn button.bg-red"); err != nil { return err }

Type guard

func canReadAttributes(e *rod.Element) bool {
    if e == nil { return false }
    _, err := e.Attribute("class")
    return err == nil
}

Try / catch

btn, reason, err := waitForPublishButtonClickable(page)
if err != nil && strings.Contains(err.Error(), "aria-disabled 属性失败") {
    time.Sleep(500 * time.Millisecond)
    btn, reason, err = waitForPublishButtonClickable(page)
}

Prevention

When it happens

Trigger: Element detached between the successful `disabled` read and the `aria-disabled` read (page re-render in between); tab closed or browser crashed during the polling loop; CDP websocket error.

Common situations: Publish page re-mounts its button list asynchronously; automation runs against an old-version page that hot-reloads in dev; connection loss to headless Chrome under memory pressure.

Related errors


AI-assisted analysis of xpzouying/xiaohongshu-mcp@332d196854 (2026-09-05). Data as JSON: /api/errors/284eb09b5380e2c2. Report an issue: GitHub.