{"record":{"id":"d894200bfd792115","repo":"xpzouying/xiaohongshu-mcp","slug":"error-d89420","errorCode":null,"errorMessage":"滚动新版发布按钮到可视区域失败","messagePattern":"滚动新版发布按钮到可视区域失败","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"xiaohongshu/publish.go","lineNumber":547,"sourceCode":"\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}\n\n\treturn nil, \"\", nil\n}\n\nfunc clickPublishWidget(page *rod.Page, widget *rod.Element) error {\n\tif err := widget.ScrollIntoView(); err != nil {\n\t\treturn errors.Wrap(err, \"滚动新版发布按钮到可视区域失败\")\n\t}\n\ttime.Sleep(200 * time.Millisecond)\n\n\tshape, err := widget.Shape()\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"获取新版发布按钮位置失败\")\n\t}\n\tif len(shape.Quads) == 0 {\n\t\treturn errors.New(\"获取新版发布按钮位置失败: 无可点击区域\")\n\t}\n\n\tquad := shape.Quads[0]\n\tminX, maxX := quad[0], quad[0]\n\tminY, maxY := quad[1], quad[1]\n\tfor i := 0; i < quad.Len(); i++ {\n\t\tx := quad[i*2]\n\t\ty := quad[i*2+1]\n\t\tif x < minX {","sourceCodeStart":529,"sourceCodeEnd":565,"githubUrl":"https://github.com/xpzouying/xiaohongshu-mcp/blob/332d196854a9eac0d2b8c2c0e3d0cc43139d724c/xiaohongshu/publish.go#L529-L565","documentation":"clickPublishWidget wraps the error returned by rod's Element.ScrollIntoView for the new-version (web component `xhs-publish-btn`) publish button. ScrollIntoView is a CDP DOM.scrollIntoViewIfNeeded call; it fails when the element is detached from the DOM or the browser connection is broken. The library cannot click the button unless it is in the viewport, so it aborts the click.","triggerScenarios":"Calling clickPublishButton while the new publish widget gets unmounted/re-created by the page; page navigated away between findPublishButton and the click; closed tab or dropped CDP connection.","commonSituations":"Uploading files changes the publish page state and re-renders the widget; clicking right after page load before hydration completes; automation running long after the browser window was closed.","solutions":["Re-run the find + click flow so a fresh element handle is obtained for the current DOM","Wait for page stability (page.WaitStable / WaitDOMStable) before clicking, especially after file upload or dialog switches","Confirm the rod page/browser is still connected; re-launch or re-open the page if the connection died","If the widget is inside a custom element shadow DOM, ensure the custom element is registered (wait for the page's JS) before scrolling"],"exampleFix":"// before\nif err := clickPublishButton(page); err != nil { return err }\n// after\n_ = page.WaitStable(300 * time.Millisecond)\nif err := clickPublishButton(page); err != nil {\n    _ = page.WaitStable(time.Second)\n    return clickPublishButton(page)\n}","handlingStrategy":"retry","validationCode":"if err := page.WaitStable(300 * time.Millisecond); err != nil { return err }\nwidgets, err := page.Elements(\"xhs-publish-btn\")\nif err != nil || len(widgets) == 0 { return errors.New(\"新版发布按钮不存在\") }\nif !isElementVisible(widgets[0]) { return errors.New(\"新版发布按钮不可见\") }","typeGuard":"func clickable(widget *rod.Element) bool {\n    if widget == nil { return false }\n    if !isElementVisible(widget) { return false }\n    shape, err := widget.Shape()\n    return err == nil && len(shape.Quads) > 0\n}","tryCatchPattern":"err := clickPublishButton(page)\nif err != nil && strings.Contains(err.Error(), \"滚动新版发布按钮到可视区域失败\") {\n    time.Sleep(500 * time.Millisecond)\n    err = clickPublishButton(page)\n}","preventionTips":["Always re-find the widget right before clicking instead of caching handles","Wait for the page's custom element to be hydrated (WaitStable) before interacting","Retry scroll+click with backoff; page re-renders are usually transient","Keep the viewport open/visible; avoid minimized headless windows during clicks"],"tags":["browser-automation","rod","cdp","scroll-into-view","element-detached"],"backgroundTag":"cdp-element-detached","analyzedSha":"332d196854a9eac0d2b8c2c0e3d0cc43139d724c","analyzedAt":"2026-09-05T22:22:55.988Z","contentChangedAt":"2026-09-05T22:22:55.988Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}