projectdiscovery/nuclei · error
http: executionId not set
Error message
http: executionId not set
What it means
Client.do found no executionId: neither the goja runtime (c.nj.ExecutionId()) nor the request context carries one. The nuclei/http client routes every dial through the per-execution fastdialer and host policy, so it fails closed when used outside a nuclei scan execution rather than silently using a default dialer.
Source
Thrown at pkg/js/libs/http/http.go:254
return defaultClient().Request(ctx, method, rawURL, body)
}
func defaultClient() *Client {
return &Client{
FollowRedirects: true,
MaxRedirects: defaultMaxRedirects,
TimeoutSeconds: defaultTimeoutSeconds,
MaxBodyBytes: defaultMaxBodyBytes,
headers: make(http.Header),
}
}
func (c *Client) do(ctx context.Context, method, rawURL, body string) (*Response, error) {
c.init()
executionID := executionIDFrom(ctx, c)
if executionID == "" {
return nil, fmt.Errorf("http: executionId not set")
}
parsed, err := url.Parse(rawURL)
if err != nil {
return nil, fmt.Errorf("http: invalid url: %w", err)
}
if parsed.Scheme == "" || parsed.Host == "" {
return nil, fmt.Errorf("http: url must include scheme and host")
}
host := parsed.Hostname()
if !protocolstate.IsHostAllowed(executionID, host) {
return nil, protocolstate.ErrHostDenied.Msgf(host)
}
dialers := protocolstate.GetDialersWithId(executionID)
if dialers == nil {
return nil, fmt.Errorf("dialers not initialized for %s", executionID)View on GitHub (pinned to 265b3a3dec)
Solutions
- Run the code as a nuclei code-protocol template so the engine attaches the executionId
- From Go/tests, seed the runtime/context exactly like nuclei: context.WithValue(ctx, "executionId", id) plus protocolstate initialization for that id
- Do not construct a Client in one runtime and use it in another
Example fix
// before: standalone script/test, no execution bound
const resp = http.Get('https://example.com'); // -> http: executionId not set
// after: run as a nuclei code template (executionId seeded automatically);
// from Go tests, mirror the engine first:
// ctx = context.WithValue(ctx, "executionId", execID)
// ... protocolstate init for execID ...
// const resp = http.Get('https://example.com'); Defensive patterns
Strategy: try-catch
Try / catch
try {
const resp = http.Get(url);
} catch (e) {
if (/executionId not set/.test(e.message || '')) {
// running outside a scan: move the code into a nuclei code template (or seed the runtime from Go)
}
} Prevention
- Use nuclei/http only inside nuclei code templates
- In SDK/tests, seed the goja runtime/context with an execution id and init protocolstate first
- Do not re-host or serialize JS clients across runtimes
When it happens
Trigger: Calling http.Get() or new http.Client().Get() from standalone Go code or tests without seeding an executionId; a runtime not initialized by nuclei's JS compiler; SDK (lib/) usage that drives the JS libraries directly.
Common situations: Embedded nuclei users exercising template logic outside the engine; unit tests invoking the http package without the scan scaffolding; tools that re-host goja runtimes without nuclei's runtime setup.
Related errors
- grpc: refusing to dial without executionId
- dialers not initialized for %s
- could not upload results got status code %v on %v
- goimpacket: no fastdialer registered for executionId %q
- grpc: dialers not initialized for executionId %q
AI-assisted analysis of projectdiscovery/nuclei@265b3a3dec (2026-08-15).
Data as JSON: /api/errors/0b7fcae9fe36fa95.
Report an issue: GitHub.