projectdiscovery/nuclei · error
invalid request type %s
Error message
invalid request type %s
What it means
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.
Source
Thrown at pkg/tmplexec/flow/flow_executor.go:91
case templateTypes.FileProtocol:
allprotos[templateTypes.FileProtocol.String()] = append(allprotos[templateTypes.FileProtocol.String()], req)
case templateTypes.HeadlessProtocol:
allprotos[templateTypes.HeadlessProtocol.String()] = append(allprotos[templateTypes.HeadlessProtocol.String()], req)
case templateTypes.SSLProtocol:
allprotos[templateTypes.SSLProtocol.String()] = append(allprotos[templateTypes.SSLProtocol.String()], req)
case templateTypes.WebsocketProtocol:
allprotos[templateTypes.WebsocketProtocol.String()] = append(allprotos[templateTypes.WebsocketProtocol.String()], req)
case templateTypes.WHOISProtocol:
allprotos[templateTypes.WHOISProtocol.String()] = append(allprotos[templateTypes.WHOISProtocol.String()], req)
case templateTypes.CodeProtocol:
allprotos[templateTypes.CodeProtocol.String()] = append(allprotos[templateTypes.CodeProtocol.String()], req)
case templateTypes.JavascriptProtocol:
allprotos[templateTypes.JavascriptProtocol.String()] = append(allprotos[templateTypes.JavascriptProtocol.String()], req)
case templateTypes.OfflineHTTPProtocol:
// offlinehttp is run in passive mode but templates are same so instead of using offlinehttp() we use http() in flow
allprotos[templateTypes.HTTPProtocol.String()] = append(allprotos[templateTypes.OfflineHTTPProtocol.String()], req)
default:
return nil, fmt.Errorf("invalid request type %s", req.Type().String())
}
}
f := &FlowExecutor{
allProtocols: allprotos,
options: options,
allErrs: mapsutil.SyncLockMap[string, error]{
ReadOnly: atomic.Bool{},
Map: make(map[string]error),
},
protoFunctions: map[string]func(call goja.FunctionCall, runtime *goja.Runtime) goja.Value{},
results: results,
ctx: ctx,
program: program,
executed: mapsutil.NewSyncLockMap[string, struct{}](),
}
return f, nil
}
View on GitHub (pinned to 265b3a3dec)
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
Example fix
# before: unsupported section inside a flow template flow: | http() requests: [] # some-toolkit-section: # custom: true # after: only supported protocol sections (http/dns/tcp/file/headless/ssl/websocket/whois/code/javascript) remain
Defensive patterns
Strategy: validation
Validate before calling
// Gate NewFlowExecutor inputs to exactly the supported switch set (flow_executor.go):
var flowSupported = map[templateTypes.ProtocolType]bool{
templateTypes.DNSProtocol: true, templateTypes.FileProtocol: true,
templateTypes.HTTPProtocol: true, templateTypes.OfflineHTTPProtocol: true,
templateTypes.HeadlessProtocol: true, templateTypes.NetworkProtocol: true,
templateTypes.SSLProtocol: true, templateTypes.WebsocketProtocol: true,
templateTypes.WHOISProtocol: true, templateTypes.CodeProtocol: true,
templateTypes.JavascriptProtocol: true,
}
for _, r := range requests {
if !flowSupported[r.Type()] {
return fmt.Errorf("request type %s cannot be used inside a flow template", r.Type().String())
}
} Type guard
func isFlowSupportedType(t templateTypes.ProtocolType) bool { return flowSupported[t] } Try / catch
f, err := flow.NewFlowExecutor(requests, ctx, options, results, program)
if err != nil {
return fmt.Errorf("template %s: %w (supported: dns,file,http,offline-http,headless,tcp,ssl,websocket,whois,code,javascript)", options.TemplateID, err)
} Prevention
- 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
When it happens
Trigger: 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().
Common situations: 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.
Related errors
- could not compile flow: %s
- validation failed for these fields
- Invalid severity: %s
- Invalid extractor type: %s
- Invalid matcher type: %s
AI-assisted analysis of projectdiscovery/nuclei@265b3a3dec (2026-08-15).
Data as JSON: /api/errors/7458f257171b233f.
Report an issue: GitHub.