{"record":{"id":"0b7fcae9fe36fa95","repo":"projectdiscovery/nuclei","slug":"http-executionid-not-set","errorCode":null,"errorMessage":"http: executionId not set","messagePattern":"http: executionId not set","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/js/libs/http/http.go","lineNumber":254,"sourceCode":"\treturn defaultClient().Request(ctx, method, rawURL, body)\n}\n\nfunc defaultClient() *Client {\n\treturn &Client{\n\t\tFollowRedirects: true,\n\t\tMaxRedirects:    defaultMaxRedirects,\n\t\tTimeoutSeconds:  defaultTimeoutSeconds,\n\t\tMaxBodyBytes:    defaultMaxBodyBytes,\n\t\theaders:         make(http.Header),\n\t}\n}\n\nfunc (c *Client) do(ctx context.Context, method, rawURL, body string) (*Response, error) {\n\tc.init()\n\n\texecutionID := executionIDFrom(ctx, c)\n\tif executionID == \"\" {\n\t\treturn nil, fmt.Errorf(\"http: executionId not set\")\n\t}\n\n\tparsed, err := url.Parse(rawURL)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"http: invalid url: %w\", err)\n\t}\n\tif parsed.Scheme == \"\" || parsed.Host == \"\" {\n\t\treturn nil, fmt.Errorf(\"http: url must include scheme and host\")\n\t}\n\n\thost := parsed.Hostname()\n\tif !protocolstate.IsHostAllowed(executionID, host) {\n\t\treturn nil, protocolstate.ErrHostDenied.Msgf(host)\n\t}\n\n\tdialers := protocolstate.GetDialersWithId(executionID)\n\tif dialers == nil {\n\t\treturn nil, fmt.Errorf(\"dialers not initialized for %s\", executionID)","sourceCodeStart":236,"sourceCodeEnd":272,"githubUrl":"https://github.com/projectdiscovery/nuclei/blob/265b3a3dec374741614e342f813c10f8b38d2bb7/pkg/js/libs/http/http.go#L236-L272","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before: standalone script/test, no execution bound\nconst resp = http.Get('https://example.com'); // -> http: executionId not set\n\n// after: run as a nuclei code template (executionId seeded automatically);\n// from Go tests, mirror the engine first:\n//   ctx = context.WithValue(ctx, \"executionId\", execID)\n//   ... protocolstate init for execID ...\n//   const resp = http.Get('https://example.com');","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  const resp = http.Get(url);\n} catch (e) {\n  if (/executionId not set/.test(e.message || '')) {\n    // running outside a scan: move the code into a nuclei code template (or seed the runtime from Go)\n  }\n}","preventionTips":["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"],"tags":["http","javascript","lifecycle","go"],"backgroundTag":null,"analyzedSha":"265b3a3dec374741614e342f813c10f8b38d2bb7","analyzedAt":"2026-08-15T20:05:51.855Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}