{"record":{"id":"e5c2d56dd75b6230","repo":"projectdiscovery/nuclei","slug":"no-navigation-action-found","errorCode":null,"errorMessage":"no navigation action found","messagePattern":"no navigation action found","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/protocols/headless/request.go","lineNumber":131,"sourceCode":"\t\t}\n\t}\n\n\treturn nil\n}\n\n// This function extracts the base URL from actions.\nfunc extractBaseURLFromActions(steps []*engine.Action) (string, error) {\n\tfor _, action := range steps {\n\t\tif action.ActionType.ActionType == engine.ActionNavigate {\n\t\t\tnavigateURL := action.GetArg(\"url\")\n\t\t\turl, err := urlutil.Parse(navigateURL)\n\t\t\tif err != nil {\n\t\t\t\treturn \"\", errors.Errorf(\"could not parse URL '%s': %s\", navigateURL, err.Error())\n\t\t\t}\n\t\t\treturn fmt.Sprintf(\"%s://%s\", url.Scheme, url.Host), nil\n\t\t}\n\t}\n\treturn \"\", errors.New(\"no navigation action found\")\n}\n\nfunc (request *Request) executeRequestWithPayloads(input *contextargs.Context, payloads map[string]interface{}, previous output.InternalEvent, interactshURLs []string, callback protocols.OutputEventCallback) error {\n\tinstance, err := request.options.Browser.NewInstance()\n\tif err != nil {\n\t\trequest.options.Output.Request(request.options.TemplatePath, input.MetaInput.Input, request.Type().String(), err)\n\t\trequest.options.Progress.IncrementFailedRequestsBy(1)\n\t\treturn errors.Wrap(err, errCouldNotGetHtmlElement)\n\t}\n\tdefer func() {\n\t\t_ = instance.Close()\n\t}()\n\n\tinstance.SetInteractsh(request.options.Interactsh)\n\n\tif _, err := url.Parse(input.MetaInput.Input); err != nil {\n\t\trequest.options.Output.Request(request.options.TemplatePath, input.MetaInput.Input, request.Type().String(), err)\n\t\trequest.options.Progress.IncrementFailedRequestsBy(1)","sourceCodeStart":113,"sourceCodeEnd":149,"githubUrl":"https://github.com/projectdiscovery/nuclei/blob/265b3a3dec374741614e342f813c10f8b38d2bb7/pkg/protocols/headless/request.go#L113-L149","documentation":"extractBaseURLFromActions derives a template's base URL by scanning its steps for an ActionNavigate action and taking the scheme+host of its url arg. A headless template whose steps contain no navigate action yields no base URL, so request compilation fails with 'no navigation action found'.","triggerScenarios":"A headless template whose steps start with extract/click/script etc. but never include `action: navigate` with a `url` arg. Nuclei does not imply an initial navigation.","commonSituations":"Assuming the browser opens the target implicitly; refactoring a workflow and deleting the navigate step as 'redundant'; building headless steps by copying fragment examples.","solutions":["Add a first step `action: navigate` with `url: '{{BaseURL}}'`","Validate the template to confirm the navigate action parses correctly"],"exampleFix":"# before\nsteps:\n  - action: extract\n    selector: 'h1'\n\n# after\nsteps:\n  - action: navigate\n    url: '{{BaseURL}}'\n  - action: extract\n    selector: 'h1'","handlingStrategy":"validation","validationCode":"hasNavigate := false\nfor _, a := range request.Steps {\n    if a.ActionType.ActionType == engine.ActionNavigate {\n        hasNavigate = true\n        break\n    }\n}\nif !hasNavigate {\n    return errors.New(\"headless template needs a navigate action\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always start headless step lists with navigate to {{BaseURL}}","When refactoring workflows, never delete the navigate step as 'redundant'"],"tags":["headless","template","navigation"],"backgroundTag":null,"analyzedSha":"265b3a3dec374741614e342f813c10f8b38d2bb7","analyzedAt":"2026-08-15T20:05:51.855Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}