{"record":{"id":"89eae6a6f4e79ac5","repo":"projectdiscovery/katana","slug":"errelementnotvisible","errorCode":"ErrElementNotVisible","errorMessage":"element not visible","messagePattern":"element not visible","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"pkg/engine/headless/crawler/crawler.go","lineNumber":484,"sourceCode":"\t\t\treturn err\n\t\t}\n\t}\n\n\terr = c.crawlGraph.AddPageState(*pageState)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// TODO: Check if the page opened new sub pages and if so capture their\n\t// navigation as well as close them so the state change can work.\n\n\tif len(navigations) == 0 && c.crawlQueue.Size() == 0 {\n\t\treturn ErrNoCrawlingAction\n\t}\n\treturn nil\n}\n\nvar ErrElementNotVisible = errors.New(\"element not visible\")\n\nfunc (c *Crawler) executeCrawlStateAction(action *types.Action, page *browser.BrowserPage) error {\n\treturn runWithActionHooks(c.options.Hooks, page, action, func() error {\n\t\treturn c.dispatchCrawlAction(action, page)\n\t})\n}\n\nfunc (c *Crawler) dispatchCrawlAction(action *types.Action, page *browser.BrowserPage) error {\n\tvar err error\n\tswitch action.Type {\n\tcase types.ActionTypeLoadURL:\n\t\t// Apply a timeout to every critical Rod call.\n\t\tpTimeout := page.Timeout(c.options.PageMaxTimeout)\n\n\t\tif err := pTimeout.Navigate(action.Input); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif err = page.WaitPageLoadHeurisitics(); err != nil {","sourceCodeStart":466,"sourceCodeEnd":502,"githubUrl":"https://github.com/projectdiscovery/katana/blob/e3e742739c3746f085943ce918fb4e2b8daf6fe6/pkg/engine/headless/crawler/crawler.go#L466-L502","documentation":"ErrElementNotVisible is returned by dispatchCrawlAction when the DOM element targeted by a crawl action cannot be made visible/interactable in the headless browser. Crawl counts it as a consecutive failure and skips the action instead of aborting the whole crawl.","triggerScenarios":"executeCrawlStateAction → dispatchCrawlAction finds an element matched by the action's selector but its visibility check fails (crawler.go:528: if !visible return ErrElementNotVisible), e.g. element hidden behind CSS (display:none), off-viewport, or covered by overlays.","commonSituations":"Crawling SPAs with lazy-loaded or modal-gated UI; consent banners covering interactive elements; animations delaying visibility when the action runs; stale selectors after page mutations.","solutions":["Let the crawler skip it — it increments consecutiveFailures and continues automatically","Re-run with slower pacing / wait options so dynamic UI has time to become visible","Audit the target page for overlays (cookie banners) and pre-dismiss via custom hooks","Update or loosen selectors in custom actions so they target always-visible elements"],"exampleFix":"// before: strict selector hitting hidden element\naction.Selector = \"#submit-button\" // display:none until form filled\n// after: trigger the visibility first\naction.Selector = \"form.open #submit-button\" // wait for state where button is visible","handlingStrategy":"retry","validationCode":"// Before executing, check the element exists and is interactable:\nel, err := page.Element(action.Selector)\nif err != nil || el == nil { skip }","typeGuard":"func isElementNotVisible(err error) bool { return errors.Is(err, crawler.ErrElementNotVisible) }","tryCatchPattern":"if errors.Is(err, crawler.ErrElementNotVisible) {\n    consecutiveFailures++\n    time.Sleep(backoff)\n    continue // retry later or skip action\n}","preventionTips":["Add wait/retry pacing so dynamic UI becomes visible before actions run","Pre-dismiss overlays (cookie banners) via hooks","Prefer selectors on stable, always-visible elements","Cap consecutiveFailures to avoid infinite retry loops"],"tags":["headless-browser","dom-visibility","action-failure"],"backgroundTag":"element-not-visible","analyzedSha":"e3e742739c3746f085943ce918fb4e2b8daf6fe6","analyzedAt":"2026-09-03T14:55:13.248Z","contentChangedAt":"2026-09-03T14:55:13.248Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}