projectdiscovery/katana · warning
ErrNoNavigationPossible
ErrNoNavigationPossible
Error message
no navigation possible
What it means
ErrNoNavigationPossible is returned by navigateBackToStateOrigin when the crawler cannot restore the browser back to a previous state's origin page hash (newPageHash == ""). Crawl's loop catches it, logs at debug level, counts a consecutive failure and skips the action, so a crawl continues but that branch of exploration is abandoned.
Source
Thrown at pkg/engine/headless/crawler/state.go:118
return state, nil
}
func sha256Hash(item string) string {
hasher := sha256.New()
hasher.Write([]byte(item))
hashItem := hex.EncodeToString(hasher.Sum(nil))
return hashItem
}
func getStrippedDOM(contents string) (string, error) {
normalized, err := domNormalizer.Apply(contents)
if err != nil {
return "", errors.Wrap(err, "could not normalize dom")
}
return normalized, nil
}
var ErrNoNavigationPossible = errors.New("no navigation possible")
// navigateBackToStateOrigin implements the logic to navigate back to the state origin
//
// It implements different logics as an optimization to decide
// how to navigate back.
//
// 1. If the action has an element, check if the element is visible on the current page
// If the element is visible, directly use that to navigate.
//
// 2. If we have browser history, and the page is in the history which was the origin
// of the action, then we can directly use the browser history to navigate back.
//
// 3. If all else fails, we have the shortest path navigation.
func (c *Crawler) navigateBackToStateOrigin(action *types.Action, page *browser.BrowserPage, currentPageHash string) (string, error) {
c.logger.Debug("Found action with different origin id",
slog.String("action_origin_id", action.OriginID),
slog.String("current_page_hash", currentPageHash),
)View on GitHub (pinned to e3e742739c)
Solutions
- Treat as skippable — the crawler already increments consecutiveFailures and moves on
- Reduce actions that open new windows (browser popup blocking options)
- Increase per-page wait/retry so navigation-back strategies have time to succeed
- Check debug logs (logger.Debug) to identify which actions cause it
Example fix
// before: aborting crawl on this error
if err := c.Crawl(ctx); err != nil { log.Fatal(err) }
// after
if err := c.Crawl(ctx); err != nil && !errors.Is(err, crawler.ErrNoNavigationPossible) { log.Fatal(err) } Defensive patterns
Strategy: try-catch
Validate before calling
// ensure history is navigable before relying on back-navigation:
if len(page.History()) < 2 { skip back-navigation strategy } Type guard
func isNoNavigationPossible(err error) bool { return errors.Is(err, crawler.ErrNoNavigationPossible) } Try / catch
if errors.Is(err, crawler.ErrNoNavigationPossible) {
log.Debug("skipping action: no navigation possible")
consecutiveFailures++
continue
} Prevention
- Block popups/new windows so actions don't orphan the current state
- Increase waits so navigation-back heuristics can succeed
- Keep sessions alive (cookies/tokens) to avoid failed replays
- Enable debug logging to find offending actions
When it happens
Trigger: After executing an action, the crawler tries to navigate back to the state origin (history back, re-navigation heuristics) and every strategy yields an empty page hash (state.go:171) — e.g. the action opened a new tab, destroyed history, or landed on about:blank.
Common situations: Actions that spawn popups or replace the document such that 'back' is impossible; sites that rewrite history (pushState loops); sessions expiring mid-crawl so replaying navigation fails.
Related errors
- ErrNoCrawlingAction
- ErrElementNotVisible
- ErrEmptyPage
- failed to get origin page state: %w
- failed to navigate back to origin page: %s != %s
AI-assisted analysis of projectdiscovery/katana@e3e742739c (2026-09-03).
Data as JSON: /api/errors/be12b052e9ffab2b.
Report an issue: GitHub.