{"record":{"id":"4aca1e22e9292767","repo":"projectdiscovery/katana","slug":"failed-to-get-origin-page-state-w","errorCode":null,"errorMessage":"failed to get origin page state: %w","messagePattern":"failed to get origin page state: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/engine/headless/crawler/state.go","lineNumber":35,"sourceCode":"\nvar emptyPageHash = sha256Hash(\"\")\n\nconst simhashThreshold = 2 // Allow up to 2 bits difference\n\nfunc (c *Crawler) isCorrectNavigation(page *browser.BrowserPage, action *types.Action) (string, *types.PageState, error) {\n\tcurrentPageHash, pageState, err := getPageHash(page)\n\tif err != nil {\n\t\treturn \"\", nil, err\n\t}\n\n\tif currentPageHash == action.OriginID {\n\t\treturn currentPageHash, pageState, nil\n\t}\n\n\t// Get the origin page state to compare SimHash\n\toriginPageState, err := c.crawlGraph.GetPageState(action.OriginID)\n\tif err != nil {\n\t\treturn \"\", pageState, fmt.Errorf(\"failed to get origin page state: %w\", err)\n\t}\n\n\tif pageState != nil && originPageState != nil {\n\t\tdistance := simhash.Distance(pageState.SimHash, originPageState.SimHash)\n\t\tif distance <= simhashThreshold {\n\t\t\tc.logger.Debug(\"Page is similar enough to origin, proceeding\",\n\t\t\t\tslog.String(\"current_hash\", currentPageHash),\n\t\t\t\tslog.String(\"origin_hash\", action.OriginID),\n\t\t\t\tslog.Uint64(\"simhash_distance\", uint64(distance)),\n\t\t\t)\n\t\t\t// Treat this page as the origin state to avoid creating a new vertex\n\t\t\treturn originPageState.UniqueID, pageState, nil\n\t\t}\n\t}\n\n\treturn \"\", pageState, fmt.Errorf(\"failed to navigate back to origin page: %s != %s\", currentPageHash, action.OriginID)\n}\n","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/projectdiscovery/katana/blob/e3e742739c3746f085943ce918fb4e2b8daf6fe6/pkg/engine/headless/crawler/state.go#L17-L53","documentation":"isCorrectNavigation failed to load the origin page state from the crawl graph before comparing SimHash distances. This error wraps the underlying GetPageState failure, so the cause is whatever the crawl graph store reported (typically the origin vertex no longer exists or the store errored). Navigation correctness cannot be evaluated without the origin state, so the check aborts.","triggerScenarios":"Calling tryBrowserHistoryNavigation or tryShortestPathNavigation with an action whose OriginID references a page state that crawlGraph.GetPageState cannot return: OriginID never persisted, graph evicted/pruned the vertex, or the store returned an I/O error.","commonSituations":"Resuming a crawl from a persisted session file where origin vertices were pruned or never saved; using an action struct copied from an older crawl run; in-memory graph reset between navigation attempts; store backend (file/db) corruption or permission errors.","solutions":["Verify action.OriginID is a valid, still-present vertex ID in the crawl graph before invoking navigation (log GetPageState for that ID).","Disable or increase graph state pruning/eviction so origin states survive until their actions are processed.","If resuming from persisted state, regenerate or re-crawl the origin page so its state exists in the graph.","Inspect the wrapped error (%w) for the root cause (not-found vs I/O) and fix the store accordingly."],"exampleFix":"// before\noriginPageState, err := c.crawlGraph.GetPageState(action.OriginID)\n// after\noriginPageState, err := c.crawlGraph.GetPageState(action.OriginID)\nif errors.Is(err, ErrPageStateNotFound) {\n    c.logger.Warn(\"origin state missing, re-crawling origin\", \"origin\", action.OriginID)\n    if _, err := c.crawlGraph.AddPageState(action.OriginID, page); err != nil {\n        return \"\", pageState, err\n    }\n    originPageState, err = c.crawlGraph.GetPageState(action.OriginID)\n}","handlingStrategy":"try-catch","validationCode":"if _, err := c.crawlGraph.GetPageState(action.OriginID); err != nil {\n    // origin state unavailable; re-crawl or skip this action before navigation\n}","typeGuard":"func hasOriginState(g *crawlGraph, id string) bool {\n    s, err := g.GetPageState(id)\n    return err == nil && s != nil\n}","tryCatchPattern":"result, err := crawler.checkNavigation(action)\nif err != nil {\n    var navErr *NavigationError\n    if errors.As(err, &navErr) && errors.Is(navErr.Unwrap(), ErrPageStateNotFound) {\n        // re-crawl origin or mark action stale\n    }\n}","preventionTips":["Never prune origin vertices while their actions are still queued.","Validate persisted session graphs on load before executing actions.","Log OriginID resolution failures with the wrapped store error for diagnosis."],"tags":["crawler","graph-store","navigation"],"backgroundTag":"page-state-not-found","analyzedSha":"e3e742739c3746f085943ce918fb4e2b8daf6fe6","analyzedAt":"2026-09-03T14:55:13.248Z","contentChangedAt":"2026-09-03T14:55:13.248Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}