{"record":{"id":"7458f257171b233f","repo":"projectdiscovery/nuclei","slug":"invalid-request-type-s","errorCode":null,"errorMessage":"invalid request type %s","messagePattern":"invalid request type (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/tmplexec/flow/flow_executor.go","lineNumber":91,"sourceCode":"\t\tcase templateTypes.FileProtocol:\n\t\t\tallprotos[templateTypes.FileProtocol.String()] = append(allprotos[templateTypes.FileProtocol.String()], req)\n\t\tcase templateTypes.HeadlessProtocol:\n\t\t\tallprotos[templateTypes.HeadlessProtocol.String()] = append(allprotos[templateTypes.HeadlessProtocol.String()], req)\n\t\tcase templateTypes.SSLProtocol:\n\t\t\tallprotos[templateTypes.SSLProtocol.String()] = append(allprotos[templateTypes.SSLProtocol.String()], req)\n\t\tcase templateTypes.WebsocketProtocol:\n\t\t\tallprotos[templateTypes.WebsocketProtocol.String()] = append(allprotos[templateTypes.WebsocketProtocol.String()], req)\n\t\tcase templateTypes.WHOISProtocol:\n\t\t\tallprotos[templateTypes.WHOISProtocol.String()] = append(allprotos[templateTypes.WHOISProtocol.String()], req)\n\t\tcase templateTypes.CodeProtocol:\n\t\t\tallprotos[templateTypes.CodeProtocol.String()] = append(allprotos[templateTypes.CodeProtocol.String()], req)\n\t\tcase templateTypes.JavascriptProtocol:\n\t\t\tallprotos[templateTypes.JavascriptProtocol.String()] = append(allprotos[templateTypes.JavascriptProtocol.String()], req)\n\t\tcase templateTypes.OfflineHTTPProtocol:\n\t\t\t// offlinehttp is run in passive mode but templates are same so instead of using offlinehttp() we use http() in flow\n\t\t\tallprotos[templateTypes.HTTPProtocol.String()] = append(allprotos[templateTypes.OfflineHTTPProtocol.String()], req)\n\t\tdefault:\n\t\t\treturn nil, fmt.Errorf(\"invalid request type %s\", req.Type().String())\n\t\t}\n\t}\n\tf := &FlowExecutor{\n\t\tallProtocols: allprotos,\n\t\toptions:      options,\n\t\tallErrs: mapsutil.SyncLockMap[string, error]{\n\t\t\tReadOnly: atomic.Bool{},\n\t\t\tMap:      make(map[string]error),\n\t\t},\n\t\tprotoFunctions: map[string]func(call goja.FunctionCall, runtime *goja.Runtime) goja.Value{},\n\t\tresults:        results,\n\t\tctx:            ctx,\n\t\tprogram:        program,\n\t\texecuted:       mapsutil.NewSyncLockMap[string, struct{}](),\n\t}\n\treturn f, nil\n}\n","sourceCodeStart":73,"sourceCodeEnd":109,"githubUrl":"https://github.com/projectdiscovery/nuclei/blob/265b3a3dec374741614e342f813c10f8b38d2bb7/pkg/tmplexec/flow/flow_executor.go#L73-L109","documentation":"NewFlowExecutor (pkg/tmplexec/flow/flow_executor.go) buckets each protocols.Request by Type() so JS functions (http(), dns(), tcp(), ...) can dispatch to them. The switch handles DNS, HTTP, Network, File, Headless, SSL, Websocket, WHOIS, Code, Javascript and OfflineHTTP; anything else hits the default and returns 'invalid request type %s' with the request's Type().String(). This is the root error that surfaces wrapped as errors 462/463.","triggerScenarios":"Any request in the list whose Type() returns WorkflowProtocol ('workflow'), InvalidProtocol ('invalid'), or zero-value/out-of-range enum. Realistically: a workflow document mistaken for a flow template, a malformed protocol section parsed into an invalid type, or an SDK-provided custom Request with an unmapped Type().","commonSituations":"Mixing workflow and flow syntax in one template; older nuclei binaries meeting newer protocol types (the switch grows over time — ssl/websocket/headless were added incrementally); programmatic template construction where the request's type tag is never set.","solutions":["Update nuclei — the flow switch is extended as protocols gain flow support","Split the template: keep only supported protocol sections in a flow template, move the rest to separate normal templates","If building requests programmatically, ensure each Request.Type() returns one of the mapped protocol types before enabling options.Flow","Validate with `nuclei -validate -t template.yaml`; a template that passes validation but still hits this on old binaries means version skew — upgrade"],"exampleFix":"# before: unsupported section inside a flow template\nflow: |\n  http()\nrequests: []\n# some-toolkit-section:\n#   custom: true\n\n# after: only supported protocol sections (http/dns/tcp/file/headless/ssl/websocket/whois/code/javascript) remain","handlingStrategy":"validation","validationCode":"// Gate NewFlowExecutor inputs to exactly the supported switch set (flow_executor.go):\nvar flowSupported = map[templateTypes.ProtocolType]bool{\n    templateTypes.DNSProtocol: true, templateTypes.FileProtocol: true,\n    templateTypes.HTTPProtocol: true, templateTypes.OfflineHTTPProtocol: true,\n    templateTypes.HeadlessProtocol: true, templateTypes.NetworkProtocol: true,\n    templateTypes.SSLProtocol: true, templateTypes.WebsocketProtocol: true,\n    templateTypes.WHOISProtocol: true, templateTypes.CodeProtocol: true,\n    templateTypes.JavascriptProtocol: true,\n}\nfor _, r := range requests {\n    if !flowSupported[r.Type()] {\n        return fmt.Errorf(\"request type %s cannot be used inside a flow template\", r.Type().String())\n    }\n}","typeGuard":"func isFlowSupportedType(t templateTypes.ProtocolType) bool { return flowSupported[t] }","tryCatchPattern":"f, err := flow.NewFlowExecutor(requests, ctx, options, results, program)\nif err != nil {\n    return fmt.Errorf(\"template %s: %w (supported: dns,file,http,offline-http,headless,tcp,ssl,websocket,whois,code,javascript)\", options.TemplateID, err)\n}","preventionTips":["Never combine workflow documents with flow templates","When nuclei adds a new protocol, wait for flow switch support before using it under `flow:`","In SDK code, assert request types before setting ExecutorOptions.Flow"],"tags":["flow","protocol-dispatch","template","validation"],"backgroundTag":null,"analyzedSha":"265b3a3dec374741614e342f813c10f8b38d2bb7","analyzedAt":"2026-08-15T20:05:51.855Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}