{"record":{"id":"95e77335e14ec568","repo":"JuliusBrussee/caveman","slug":"element-not-actionable-last-box-v","errorCode":null,"errorMessage":"element not actionable: last box=%+v","messagePattern":"element not actionable: last box=%\\+v","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"browse/cdp.go","lineNumber":284,"sourceCode":"\t\t\t}\n\t\t\tx2, y2, w2, h2, err2 := d.box(ctx, target)\n\t\t\tstable := err2 == nil && math.Abs(x-x2) < 0.5 && math.Abs(y-y2) < 0.5 && math.Abs(w-w2) < 0.5 && math.Abs(h-h2) < 0.5\n\t\t\tif stable {\n\t\t\t\tvisible, err := d.visible(ctx, target)\n\t\t\t\tif err == nil && visible {\n\t\t\t\t\tenabled, err := d.enabled(ctx, target)\n\t\t\t\t\tif err == nil && enabled {\n\t\t\t\t\t\tok, err := d.receivesEvents(ctx, target, x2, y2)\n\t\t\t\t\t\tif err == nil && ok {\n\t\t\t\t\t\t\treturn x2, y2, nil\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tlast = boxPoint{x: x2, y: y2, w: w2, h: h2}\n\t\t}\n\t\tif time.Now().After(deadline) {\n\t\t\treturn 0, 0, fmt.Errorf(\"element not actionable: last box=%+v\", last)\n\t\t}\n\t\tselect {\n\t\tcase <-ctx.Done():\n\t\t\treturn 0, 0, ctx.Err()\n\t\tcase <-time.After(100 * time.Millisecond):\n\t\t}\n\t}\n}\n\ntype boxPoint struct {\n\tx float64\n\ty float64\n\tw float64\n\th float64\n}\n\nfunc (d *CDPDriver) box(ctx context.Context, target Target) (float64, float64, float64, float64, error) {\n\tif target.BackendDOMNodeID <= 0 {","sourceCodeStart":266,"sourceCodeEnd":302,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/browse/cdp.go#L266-L302","documentation":"waitActionable polls an element's bounding box until it is visible, stable, and positioned where a real interaction can land. If the element still fails actionability checks when the deadline expires, it fails closed with 'element not actionable: last box=<last observed geometry>' so agents never click invisible or moving targets.","triggerScenarios":"Calling Act on an element whose box never stabilizes or is zero/off-screen within the wait deadline: element hidden by CSS (display:none, zero size), covered by overlays, constantly re-rendering, or detached and replaced so its box keeps resetting.","commonSituations":"Animating or skeleton-loading UIs where the box never settles; modals/spinners covering the target; virtualized lists replacing DOM nodes; lazy-rendered content that never appears because a prerequisite step (scroll, login) was skipped; selectors matching an invisible wrapper element.","solutions":["Inspect the last box in the error: width/height 0 means hidden or not rendered — fix the selector to target the visible interactive element, or trigger rendering (scroll/click) first","Increase the actionability deadline for slow pages, or add explicit waits for the loading overlay to disappear before acting","If the element moves continuously (animations), disable the animation in the page or wait for it to finish before dispatching the action"],"exampleFix":"// before\nres, err := driver.Act(ctx, browse.ActionRequest{Target: \"#submit\"}) // hidden during skeleton load\n// after\nif err := driver.WaitForHidden(ctx, \".skeleton-loader\"); err != nil { return err } // or extend deadline\nres, err := driver.Act(ctx, browse.ActionRequest{Target: \"#submit\"})","handlingStrategy":"retry","validationCode":"// check visibility before acting\nvisible, err := driver.IsVisible(ctx, target)\nif err != nil || !visible { return fmt.Errorf(\"target %s not visible yet\", target) }","typeGuard":null,"tryCatchPattern":"res, err := driver.Act(ctx, req)\nif err != nil && strings.Contains(err.Error(), \"element not actionable\") {\n\t// inspect last box: zero-size => hidden; moving => wait for animation;\n\t// then retry with a longer deadline or corrected selector\n}","preventionTips":["Wait for loading overlays/skeletons to disappear before dispatching actions","Target visible interactive elements, not hidden wrappers","Extend deadlines on slow or animated pages","Re-resolve the target after DOM replacement (virtualized lists)"],"tags":["go","browser","cdp","timeout","automation","actionability"],"backgroundTag":"element-not-actionable","analyzedSha":"3ee70a102609e550bd2e68004bf5990a9341c851","analyzedAt":"2026-09-20T15:53:39.229Z","contentChangedAt":"2026-09-20T15:53:39.229Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}