projectdiscovery/katana · error

could not enable fetch domain

Error message

could not enable fetch domain

What it means

handlePageDialogBoxes (called during page creation) enables the Chrome DevTools Fetch domain via proto.FetchEnable{...}.Call(b.Page) so katana can intercept responses and auto-dismiss JS dialogs; failure is wrapped as 'could not enable fetch domain'. This means the CDP Fetch.enable command was rejected — usually because the page/browser session is dead or the domain is already in an inconsistent state.

Source

Thrown at pkg/engine/headless/browser/browser.go:505

// It combines the functionality of BackoffSleeper and CountSleeper.
func backoffCountSleeper(initInterval, maxInterval time.Duration, maxAttempts int, algorithm func(time.Duration) time.Duration) rodutils.Sleeper {
	backoff := rodutils.BackoffSleeper(initInterval, maxInterval, algorithm)
	count := rodutils.CountSleeper(maxAttempts)

	return rodutils.EachSleepers(backoff, count)
}

func (b *BrowserPage) handlePageDialogBoxes() error {
	err := proto.FetchEnable{
		Patterns: []*proto.FetchRequestPattern{
			{
				URLPattern:   "*",
				RequestStage: proto.FetchRequestStageResponse,
			},
		},
	}.Call(b.Page)
	if err != nil {
		return errors.Wrap(err, "could not enable fetch domain")
	}

	go b.EachEvent(
		func(e *proto.PageJavascriptDialogOpening) {
			_ = proto.PageHandleJavaScriptDialog{
				Accept:     true,
				PromptText: xid.New().String(),
			}.Call(b.Page)
		},

		func(e *proto.FetchRequestPaused) {
			if b.launcher.opts.CookieConsentBypass {
				// Check if request should be blocked by cookie consent rules
				var originStr string
				if origin, ok := e.Request.Headers["Origin"]; ok {
					originStr = origin.Str()
				}
				if cookie.ShouldBlockRequest(e.Request.URL, e.ResourceType, originStr) {

View on GitHub (pinned to e3e742739c)

Solutions

  1. Check the wrapped error for 'target closed'/'session not found' and recreate the browser page (the whole createBrowserPageFunc path) instead of retrying FetchEnable.
  2. Verify the Chrome instance is alive and the remote debugging WebSocket URL is valid and reachable.
  3. Lower crawl concurrency so Chrome is not killed by resource exhaustion mid-setup.
  4. Update Chrome/katana to matching versions so the Fetch domain behaves as expected.

Example fix

// before: ignoring why fetch enable failed
if err := browserPage.handlePageDialogBoxes(); err != nil { return err }

// after: recreate the page when the session is dead
if err := browserPage.handlePageDialogBoxes(); err != nil {
    if strings.Contains(err.Error(), "target closed") || strings.Contains(err.Error(), "session") {
        return l.createBrowserPageFunc() // fresh browser/page
    }
    return err
}
Defensive patterns

Strategy: try-catch

Validate before calling

// confirm CDP session is usable before enabling Fetch
if page.GetContext().Err() != nil {
    return fmt.Errorf("cannot enable fetch domain: page session dead")
}

Try / catch

if err := proto.FetchEnable{Patterns: ...}.Call(page); err != nil {
    if strings.Contains(err.Error(), "already enabled") {
        return nil // idempotent: treat as success
    }
    return errors.Wrap(err, "could not enable fetch domain") // dead session: recreate page
}

Prevention

When it happens

Trigger: Calling FetchEnable on a page whose CDP connection is closed or whose target crashed, on an already-disconnected remote browser, or when the underlying session returns 'session not found' / 'target closed' during browser page setup.

Common situations: Chrome dying between page creation and dialog-handler setup in fast-crawl/high-concurrency runs; using a stale remote debugging endpoint (ChromeWSUrl) that has dropped; older Chrome builds with Fetch domain quirks; page pool reuse after the browser was closed.

Related errors


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