projectdiscovery/katana · error
could not get forms
Error message
could not get forms
What it means
This error is a wrapper produced by BrowserPage.FindNavigations (katana headless engine) when b.GetAllForms() fails. GetAllForms evaluates `window.getAllForms()` in the page context via the Chrome DevTools Protocol; failure means the CDP eval itself errored or the returned JSON could not be unmarshaled into []*types.HTMLForm. It aborts the navigation-discovery step, so no actions (forms/buttons/links) are returned for the page.
Source
Thrown at pkg/engine/headless/browser/element.go:66
// FindNavigation attempts to find more navigations on the page which could
// be done to find more links and pages.
//
// This includes the following -
// 1. Forms
// 2. Buttons
// 3. Links
// 4. Elements with event listeners
//
// The navigations found are unique across the page. The caller
// needs to ensure they are unique globally before doing further actions with details.
func (b *BrowserPage) FindNavigations() ([]*types.Action, error) {
unique := make(map[string]struct{})
navigations := make([]*types.Action, 0)
forms, err := b.GetAllForms()
if err != nil {
return nil, errors.Wrap(err, "could not get forms")
}
for _, form := range forms {
for _, element := range form.Elements {
if element.TagName != "BUTTON" {
continue
}
// TODO: Check if this button is already in the unique map
// and if so remove it
unique[element.Hash()] = struct{}{}
}
hash := form.Hash()
if _, found := unique[hash]; found {
continue
}
unique[hash] = struct{}{}
navigations = append(navigations, &types.Action{
Type: types.ActionTypeFillForm,View on GitHub (pinned to e3e742739c)
Solutions
- Retry FindNavigations once after the page has fully loaded; transient CDP context errors often resolve after a re-load
- Check that the target URL is reachable and does not crash the tab (test manually in Chrome)
- Reduce concurrency/headless resource usage and re-run
- Update katana; newer builds harden eval/unmarshal failures
Example fix
// before
navigations, err := page.FindNavigations()
if err != nil { return err }
// after
navigations, err := page.FindNavigations()
if err != nil {
logger.Debug("navigation discovery failed, skipping page", slog.String("error", err.Error()))
return nil // degrade gracefully instead of failing the crawl
} Defensive patterns
Strategy: fallback
Validate before calling
// ensure the page is live and loaded before discovery
if page == nil || page.Closed() { return nil }
if err := page.WaitPageLoadHeurisitics(); err != nil { return nil } Type guard
func pageUsable(p *browser.BrowserPage) bool { return p != nil && !p.Closed() } Try / catch
navs, err := page.FindNavigations()
if err != nil {
if _, isCtx := errors.Cause(err).(*cdp.ExecutionContextDestroyedError); isCtx {
return retryOnce(page) // transient
}
return nil // skip page
} Prevention
- Wait for load completion before DOM discovery
- Retry transient CDP eval errors once
- Keep browser memory sane to avoid renderer crashes
- Skip (don't fail) the crawl on per-page discovery errors
When it happens
Trigger: 1) The page/tab was closed or crashed so the CDP eval fails. 2) Navigation destroyed the execution context mid-crawl (the page changed while FindNavigations ran). 3) The injected window.getAllForms helper is missing because page scripts/init scripts were not installed on the new document. 4) The eval result could not be JSON-unmarshaled into HTMLForm structs (unexpected shape).
Common situations: Crawling SPAs that replace the document frequently; crawling a page that redirects or closes tabs; browser resource exhaustion (renderer crash) under heavy concurrency; custom hook code removing injected helpers.
Related errors
- could not get buttons
- could not get links
- could not get page info
- could not get event listeners
- could not get page state
AI-assisted analysis of projectdiscovery/katana@e3e742739c (2026-09-03).
Data as JSON: /api/errors/271c66be15651b14.
Report an issue: GitHub.