{"record":{"id":"5af5e26429f31857","repo":"xpzouying/xiaohongshu-mcp","slug":"error-5af5e2","errorCode":null,"errorMessage":"元素无可悬停区域","messagePattern":"元素无可悬停区域","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"humanize/input.go","lineNumber":139,"sourceCode":"\n\tmouse := elem.Page().Mouse\n\tif err := moveMouseCurved(mouse, target); err != nil {\n\t\treturn err\n\t}\n\treturn pressAndRelease(mouse)\n}\n\nfunc MoveTo(page *rod.Page, pt proto.Point) error {\n\treturn moveMouseCurved(page.Mouse, pt)\n}\n\nfunc Hover(elem *rod.Element) error {\n\tshape, err := elem.Shape()\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(shape.Quads) == 0 {\n\t\treturn errors.New(\"元素无可悬停区域\")\n\t}\n\n\tq := shape.Quads[0]\n\tcenter := proto.Point{X: (q[0] + q[4]) / 2, Y: (q[1] + q[5]) / 2}\n\n\ttarget := jitterInQuad(center, q)\n\tif err := ensureClickable(elem, target); err != nil {\n\t\treturn err\n\t}\n\n\treturn moveMouseCurved(elem.Page().Mouse, target)\n}\n\nfunc ClickAt(page *rod.Page, pt proto.Point) error {\n\tif err := ensurePointInViewport(page, pt); err != nil {\n\t\treturn err\n\t}\n\tif err := moveMouseCurved(page.Mouse, pt); err != nil {","sourceCodeStart":121,"sourceCodeEnd":157,"githubUrl":"https://github.com/xpzouying/xiaohongshu-mcp/blob/332d196854a9eac0d2b8c2c0e3d0cc43139d724c/humanize/input.go#L121-L157","documentation":"Raised in Hover (humanize/input.go:139) when the element's Shape() has no quads, so there is no hoverable area. The humanized hover needs quad geometry to compute a center and jitter target; a zero-quad shape means the browser cannot provide a box for the element.","triggerScenarios":"Calling humanize.Hover on a hidden (display:none), detached, or zero-size element — `len(shape.Quads) == 0` triggers the error. In this repo it is called from Search when hovering search results.","commonSituations":"Hovering a search-result card while the list is still rendering or was virtualized away; hovering elements inside collapsed containers; stale handles after DOM updates during scraping.","solutions":["Wait until the target is rendered (WaitVisible + WaitStable) before Hover","Re-query the element inside the current DOM, especially after infinite-scroll updates","Skip elements with no geometry — filter result items by bounding box before hovering","Add humanized delays so lazy-rendered content has time to appear before the hover"],"exampleFix":"// before\ncard, _ := page.Element(\".note-item\")\nhumanize.Hover(card)\n// after\ncard, _ := page.WaitVisible(\".note-item\")\npage.WaitStable()\nhumanize.Hover(card)","handlingStrategy":"validation","validationCode":"shape, err := elem.Shape()\nif err == nil && len(shape.Quads) > 0 { /* hoverable area exists */ }","typeGuard":"func hasHoverArea(elem *rod.Element) bool {\n    s, err := elem.Shape()\n    return err == nil && len(s.Quads) > 0\n}","tryCatchPattern":"if err := humanize.Hover(card); err != nil {\n    if strings.Contains(err.Error(), \"无可悬停区域\") {\n        return nil // skip item with no geometry\n    }\n    return err\n}","preventionTips":["WaitVisible before hovering lazy-rendered list items","Filter virtualized/removed items by bounding box before hover","Re-query elements after scroll-triggered renders"],"tags":["dom","geometry","go-rod","humanize"],"backgroundTag":"element-not-clickable","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"}