projectdiscovery/nuclei · error

Element did not appear in the given amount of time

Error message

Element did not appear in the given amount of time

What it means

Produced by the waitfor action path: the page is polled with a backoff sleeper (pollTime up to timeout) via pageElementBy; if that lookup errors, or the element is found but never becomes visible (element.WaitVisible), the underlying error is wrapped with 'Element did not appear in the given amount of time'. A nil lookup result returns the bare error.

Source

Thrown at pkg/protocols/headless/engine/page_actions.go:225

	}

	pollTime, err := getTimeParameter(p, act, "pollTime", 100, time.Millisecond)
	if err != nil {
		return errors.Wrap(err, "Wrong polling time given")
	}

	lookupPage := p.Sleeper(pollTime, timeout).Timeout(timeout)
	element, _, err := p.pageElementBy(lookupPage.Page(), act)
	if err != nil {
		return errors.Wrap(err, errElementDidNotAppear)
	}

	if element != nil {
		if err := element.WaitVisible(); err != nil {
			return errors.Wrap(err, errElementDidNotAppear)
		}
	} else {
		return errors.New(errElementDidNotAppear)
	}

	return nil
}

func (p *Page) Sleeper(pollTimeout, timeout time.Duration) *Page {
	page := *p
	page.page = page.Page().Sleeper(func() utils.Sleeper {
		return createBackOffSleeper(pollTimeout, timeout)
	})
	return &page
}

func (p *Page) Timeout(timeout time.Duration) *Page {
	page := *p
	page.page = page.Page().Timeout(timeout)
	return &page
}

View on GitHub (pinned to 265b3a3dec)

Solutions

  1. Verify the selector matches in browser DevTools on the actual rendered page
  2. Raise the wait budget: `timeout` arg on the action and/or -page-timeout globally
  3. Precede waitfor with waitload/waitidle so the DOM settles before polling starts
  4. Loosen the selector (partial attribute match, XPath contains()) to survive markup drift

Example fix

# before
- action: waitfor
  selector: '#dashboard-user-profile-9281'

# after
- action: waitload
- action: waitfor
  selector: '[id*="user-profile"]'
  timeout: 15000
Defensive patterns

Strategy: try-catch

Try / catch

err := page.WaitDOMContentLoaded() // no; concrete pattern:
if err := instance.Run(...); err != nil {
    if strings.Contains(err.Error(), errElementDidNotAppear) {
        // selector/timeout problem: log target for manual review, do not abort the whole scan
        gologger.Warning().Msgf("element not found on %s", target)
        continue
    }
    return err
}

Prevention

When it happens

Trigger: A `action: waitfor` step with a selector/XPath that never matches before the timeout elapses; SPA content that renders later than page-timeout; anti-bot pages that replace the DOM before the element becomes visible.

Common situations: Selectors copied from a page whose markup has since changed; timeouts left at default while the target app is slow; element behind a login/interaction so it never appears on the initial page.

Related errors


AI-assisted analysis of projectdiscovery/nuclei@265b3a3dec (2026-08-15). Data as JSON: /api/errors/b6593a0624e0357f. Report an issue: GitHub.