xpzouying/xiaohongshu-mcp · warning

读取 checkbox 状态失败

Error message

读取 checkbox 状态失败

What it means

checkFooterCheckbox wraps a failure from cb.Eval with this message. The read-only JS snippet checking input.checked or a .checked class could not run — typically because the element's execution context vanished or the object was garbage-collected by rod between lookup and eval. Callers only warn upstream, but the checkbox state stays unknown.

Source

Thrown at xiaohongshu/publish.go:1106

		}
	}
	return nil, errors.Errorf("未找到包含%q的弹窗 footer", keyword)
}

// checkFooterCheckbox 勾选 footer 内的自定义 checkbox(未勾选时才点)。
func checkFooterCheckbox(footer *rod.Element) error {
	cb, err := footer.Element("div.d-checkbox")
	if err != nil {
		return errors.Wrap(err, "未找到须知 checkbox")
	}

	// 只读判断当前是否已勾选(隐藏 input.checked 或 simulator 上的 checked 态)
	checked, err := cb.Eval(`() => {
		const input = this.querySelector('input[type="checkbox"]');
		return (input && input.checked) || this.querySelector('.checked') !== null;
	}`)
	if err != nil {
		return errors.Wrap(err, "读取 checkbox 状态失败")
	}
	if checked.Value.Bool() {
		return nil
	}

	return humanize.Click(cb)
}

func isButtonDisabled(btn *rod.Element) bool {
	if disabled, _ := btn.Attribute("disabled"); disabled != nil {
		return true
	}
	if cls, _ := btn.Attribute("class"); cls != nil && hasExactClass(*cls, "disabled") {
		return true
	}
	return false
}

View on GitHub (pinned to 332d196854)

Solutions

  1. Re-locate the checkbox and retry the Eval once on failure
  2. Wait for the element to be stable (WaitStable) before evaluating
  3. Check the wrapped inner error for 'object reference chain too long'/'detached' hints and treat as re-render
  4. Replace fixed sleeps with waits so eval happens after rendering settles

Example fix

// before
checked, err := cb.Eval(`() => { ... }`)
if err != nil {
    return errors.Wrap(err, "读取 checkbox 状态失败")
}
// after
if err := cb.WaitStable(); err != nil { return err }
checked, err := cb.Eval(`() => { ... }`)
if err != nil {
    cb, err = footer.Element("div.d-checkbox")
    if err != nil { return err }
    checked, err = cb.Eval(`() => { ... }`)
}
Defensive patterns

Strategy: retry

Validate before calling

// ensure element still attached before eval
if alive, err := cb.Eval("() => document.contains(this)"); err == nil && !alive.Value.Bool() {
    cb, err = footer.Element("div.d-checkbox") // re-locate
}

Try / catch

err := checkFooterCheckbox(footer)
if err != nil && strings.Contains(err.Error(), "读取 checkbox 状态失败") {
    time.Sleep(500 * time.Millisecond)
    err = checkFooterCheckbox(footer) // single retry after re-render settles
}

Prevention

When it happens

Trigger: The dialog re-rendered between footer.Element and cb.Eval (element detached); the page navigated away; the rod context expired during evaluation.

Common situations: Animations/React re-renders replacing the checkbox node right after lookup; slow pages combined with fixed sleeps; browser crash mid-flow.

Related errors


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