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

  1. Retry FindNavigations once after the page has fully loaded; transient CDP context errors often resolve after a re-load
  2. Check that the target URL is reachable and does not crash the tab (test manually in Chrome)
  3. Reduce concurrency/headless resource usage and re-run
  4. 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

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


AI-assisted analysis of projectdiscovery/katana@e3e742739c (2026-09-03). Data as JSON: /api/errors/271c66be15651b14. Report an issue: GitHub.