{"record":{"id":"aa43de3dc9521ce7","repo":"projectdiscovery/nuclei","slug":"grpc-dialers-not-initialized-for-executionid-q","errorCode":null,"errorMessage":"grpc: dialers not initialized for executionId %q","messagePattern":"grpc: dialers not initialized for executionId %q","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/js/libs/grpc/invoke.go","lineNumber":58,"sourceCode":"// (instead of gRPC's built in DNS resolver), keeping resolution and policy\n// enforcement inside fastdialer.\nfunc dialTarget(ctx context.Context, executionID, target string, cfg connConfig) (*grpc.ClientConn, error) {\n\thost, _, err := net.SplitHostPort(target)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"invalid grpc target %q (expected host:port): %w\", target, err)\n\t}\n\tif host == \"\" {\n\t\treturn nil, fmt.Errorf(\"grpc target host cannot be empty\")\n\t}\n\tif executionID == \"\" {\n\t\treturn nil, fmt.Errorf(\"grpc: refusing to dial without executionId\")\n\t}\n\tif !protocolstate.IsHostAllowed(executionID, host) {\n\t\treturn nil, protocolstate.ErrHostDenied.Msgf(host)\n\t}\n\tdialers := protocolstate.GetDialersWithId(executionID)\n\tif dialers == nil || dialers.Fastdialer == nil {\n\t\treturn nil, fmt.Errorf(\"grpc: dialers not initialized for executionId %q\", executionID)\n\t}\n\n\tcontextDialer := func(dialCtx context.Context, addr string) (net.Conn, error) {\n\t\treturn dialers.Fastdialer.Dial(dialCtx, \"tcp\", addr)\n\t}\n\n\tvar creds credentials.TransportCredentials\n\tif cfg.plaintext {\n\t\tcreds = insecure.NewCredentials()\n\t} else {\n\t\tserverName := cfg.serverName\n\t\tif serverName == \"\" {\n\t\t\tserverName = host\n\t\t}\n\t\tcreds = credentials.NewTLS(&tls.Config{\n\t\t\tInsecureSkipVerify: cfg.insecureSkipVerify,\n\t\t\tServerName:         serverName,\n\t\t\tMinVersion:         tls.VersionTLS12,","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/projectdiscovery/nuclei/blob/265b3a3dec374741614e342f813c10f8b38d2bb7/pkg/js/libs/grpc/invoke.go#L40-L76","documentation":"An executionId was present but protocolstate.GetDialersWithId(executionID) returned nil or lacked Fastdialer: no per-execution dialer set is registered (never initialized, already torn down, or an id mismatch), so the gRPC connection cannot be routed through fastdialer and host policy.","triggerScenarios":"Client.Connect()/Invoke() racing with execution teardown; an SDK flow that sets an executionId but skips protocolstate initialization; a Client cached from a previous execution being reused after its dialers were released.","commonSituations":"Holding a grpc.Client in a module-level variable across template executions; embedded nuclei flows that bypass the standard engine initialization; cleanup goroutines closing dialers while reflection is still running.","solutions":["Create the grpc.Client, invoke, and Close() within a single execution lifetime","Ensure protocolstate dialers are initialized for the execution before the first Connect/Invoke","Do not cache clients across scans; re-create them per execution"],"exampleFix":"// before: client cached across executions, dialers of the first execution long gone\nlet cached;\nfunction probe(t) {\n  cached = cached || new grpc.Client(t);\n  return cached.Invoke('acme.v1.Svc/Get', '{}');\n}\n\n// after: construct, use, close inside one execution\nfunction probe(t) {\n  const c = new grpc.Client(t);\n  try { return c.Invoke('acme.v1.Svc/Get', '{}'); }\n  finally { c.Close(); }\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  const c = new grpc.Client(target, opts);\n  try { return c.Invoke(method, msg); } finally { c.Close(); }\n} catch (e) {\n  if (/dialers not initialized/.test(e.message || '')) {\n    // execution lifecycle bug: re-create the client inside a live execution; do not cache across scans\n  }\n}","preventionTips":["Construct, use, and Close() the grpc.Client within a single execution","Never cache clients in module-level variables across template runs","Ensure protocolstate is initialized before the first Connect/Invoke"],"tags":["grpc","lifecycle","dialer","javascript"],"backgroundTag":null,"analyzedSha":"265b3a3dec374741614e342f813c10f8b38d2bb7","analyzedAt":"2026-08-15T20:05:51.855Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}