{"record":{"id":"9b0284b83a06259e","repo":"xpzouying/xiaohongshu-mcp","slug":"disabled","errorCode":null,"errorMessage":"读取旧版发布按钮 disabled 属性失败","messagePattern":"读取旧版发布按钮 disabled 属性失败","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"xiaohongshu/publish.go","lineNumber":522,"sourceCode":"\t\tif submitDisabled != nil && *submitDisabled == \"true\" {\n\t\t\treturn &publishButton{elem: widget, isWidget: true}, \"新版发布按钮不可点击\", nil\n\t\t}\n\n\t\treturn &publishButton{elem: widget, isWidget: true}, \"\", nil\n\t}\n\n\toldButtons, err := page.Elements(\".publish-page-publish-btn button.bg-red\")\n\tif err != nil {\n\t\treturn nil, \"\", errors.Wrap(err, \"查找旧版发布按钮失败\")\n\t}\n\n\tfor _, oldButton := range oldButtons {\n\t\tif !isElementVisible(oldButton) {\n\t\t\tcontinue\n\t\t}\n\n\t\tif disabled, err := oldButton.Attribute(\"disabled\"); err != nil {\n\t\t\treturn nil, \"\", errors.Wrap(err, \"读取旧版发布按钮 disabled 属性失败\")\n\t\t} else if disabled != nil {\n\t\t\treturn &publishButton{elem: oldButton}, \"旧版发布按钮 disabled\", nil\n\t\t}\n\n\t\tif ariaDisabled, err := oldButton.Attribute(\"aria-disabled\"); err != nil {\n\t\t\treturn nil, \"\", errors.Wrap(err, \"读取旧版发布按钮 aria-disabled 属性失败\")\n\t\t} else if ariaDisabled != nil && *ariaDisabled == \"true\" {\n\t\t\treturn &publishButton{elem: oldButton}, \"旧版发布按钮 aria-disabled=true\", nil\n\t\t}\n\n\t\tif cls, err := oldButton.Attribute(\"class\"); err != nil {\n\t\t\treturn nil, \"\", errors.Wrap(err, \"读取旧版发布按钮 class 属性失败\")\n\t\t} else if cls != nil && hasExactClass(*cls, \"disabled\") {\n\t\t\treturn &publishButton{elem: oldButton}, \"旧版发布按钮包含 disabled class\", nil\n\t\t}\n\n\t\treturn &publishButton{elem: oldButton}, \"\", nil\n\t}","sourceCodeStart":504,"sourceCodeEnd":540,"githubUrl":"https://github.com/xpzouying/xiaohongshu-mcp/blob/332d196854a9eac0d2b8c2c0e3d0cc43139d724c/xiaohongshu/publish.go#L504-L540","documentation":"This error is wrapped in findPublishButton when the CDP call to read the `disabled` attribute of a visible legacy (old-version) Xiaohongshu publish button fails. It means the rod Element.Attribute call itself errored (browser/tab closed, element detached, CDP communication failure), not that the button is disabled. The library throws it because it cannot determine clickability without the attribute value.","triggerScenarios":"Calling waitForPublishButtonClickable while the page is being navigated or reloading so the matched `.publish-page-publish-btn button.bg-red` element is detached between query and attribute read; the browser context/tab was closed mid-poll; CDP connection dropped.","commonSituations":"Slow page loads where the old publish button is replaced by React re-renders; user closes the Chrome window during automation; network hiccup breaking the DevTools websocket; running against a stale rod.Page after navigation.","solutions":["Retry waitForPublishButtonClickable with a small delay — the element likely got detached by a page re-render; the polling loop will re-query fresh elements","Check that the browser process and target tab are still alive (rod.Browser / page.MustTarget) before retrying","Increase page load waits (page.WaitStable / WaitDOMStable) before triggering publish so elements stop mutating mid-check","Upgrade rod to the latest version to rule out known CDP race bugs"],"exampleFix":"// before\nbtn, reason, err := waitForPublishButtonClickable(page)\n// after\nerr = page.WaitDOMStable(time.Second, 0.1)\nif err != nil { return err }\nbtn, reason, err := waitForPublishButtonClickable(page)","handlingStrategy":"retry","validationCode":"if page == nil { return errors.New(\"page 未初始化\") }\nif err := page.WaitStable(300 * time.Millisecond); err != nil { return err }","typeGuard":"func pageAlive(page *rod.Page) bool {\n    if page == nil { return false }\n    _, err := page.Elements(\"body\")\n    return err == nil\n}","tryCatchPattern":"btn, reason, err := waitForPublishButtonClickable(page)\nif err != nil {\n    if strings.Contains(err.Error(), \"读取旧版发布按钮 disabled 属性失败\") {\n        time.Sleep(500 * time.Millisecond)\n        btn, reason, err = waitForPublishButtonClickable(page)\n    }\n    if err != nil { return err }\n}","preventionTips":["Wait for DOM stability before starting publish-button polling","Keep the browser window/tab open for the whole automation run","Wrap attribute-reading steps in a retry loop with backoff","Monitor the CDP connection and re-launch on disconnect"],"tags":["browser-automation","rod","cdp","element-detached"],"backgroundTag":"cdp-element-attribute-failed","analyzedSha":"332d196854a9eac0d2b8c2c0e3d0cc43139d724c","analyzedAt":"2026-09-05T22:22:55.988Z","contentChangedAt":"2026-09-05T22:22:55.988Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}