projectdiscovery/nuclei · error
goimpacket: no fastdialer registered for executionId %q
Error message
goimpacket: no fastdialer registered for executionId %q
What it means
The context carried an executionId, but protocolstate.GetDialersWithId(execID) returned nil (or a record without Fastdialer), meaning no dialer set was registered for that execution. The exec-bound dial path refuses to fall back to a default dialer, so it fails closed instead of bypassing fastdialer and host policy.
Source
Thrown at pkg/js/libs/gptransport/dialer.go:55
return &gptr.Dialer{
DialFn: func(ctx context.Context, network, address string) (net.Conn, error) {
return DialWithExec(ctx, execID, network, address)
},
}
}
// DialWithExec performs the fastdialer dial after enforcing host policy.
func DialWithExec(ctx context.Context, execID, network, address string) (net.Conn, error) {
host, _, err := net.SplitHostPort(address)
if err != nil {
return nil, fmt.Errorf("invalid address %q: %w", address, err)
}
if !protocolstate.IsHostAllowed(execID, host) {
return nil, protocolstate.ErrHostDenied.Msgf(host)
}
dialer := protocolstate.GetDialersWithId(execID)
if dialer == nil || dialer.Fastdialer == nil {
return nil, fmt.Errorf("goimpacket: no fastdialer registered for executionId %q", execID)
}
return dialer.Fastdialer.Dial(ctx, network, address)
}
// ExecutionIDFromCtx pulls the executionId set by nuclei on its goja runtime
// or scan context. Returns "" when the context carries no id.
func ExecutionIDFromCtx(ctx context.Context) string {
if ctx == nil {
return ""
}
if v := ctx.Value("executionId"); v != nil {
if id, ok := v.(string); ok {
return id
}
}
return ""
}
View on GitHub (pinned to 265b3a3dec)
Solutions
- Initialize/verify protocolstate dialers for the executionId before starting any work that dials
- Cancel or complete in-flight goimpacket work before the execution's dialers are released
- Log the execID at both registration and dial time and confirm they match exactly
Example fix
// before: dials before dialers exist (or after they were released)
conn, err := gptransport.DialWithExec(ctx, execID, "tcp", addr)
// after: fail fast with a lifecycle hint instead of an opaque dial error
if d := protocolstate.GetDialersWithId(execID); d == nil || d.Fastdialer == nil {
return fmt.Errorf("dialers not registered for execution %s; initialize protocolstate first", execID)
}
conn, err := gptransport.DialWithExec(ctx, execID, "tcp", addr) Defensive patterns
Strategy: validation
Validate before calling
if d := protocolstate.GetDialersWithId(execID); d == nil || d.Fastdialer == nil {
return fmt.Errorf("no dialers registered for execution %s; initialize protocolstate first", execID)
}
conn, err := gptransport.DialWithExec(ctx, execID, "tcp", addr) Type guard
func hasRegisteredDialers(execID string) bool {
d := protocolstate.GetDialersWithId(execID)
return d != nil && d.Fastdialer != nil
} Try / catch
if err != nil && strings.Contains(err.Error(), "no fastdialer registered") {
// lifecycle bug: dialers uninitialized or released; re-init or abort, do not silently retry Prevention
- Initialize protocolstate dialers per execution before any dialing goroutine starts
- Complete or cancel SMB/DCOM work before the execution is torn down
- Log the executionId at registration and at dial time to catch mismatches early
When it happens
Trigger: protocolstate was never initialized for the execution; the execution already finished and its dialers were released while a goroutine still dials; the executionId in the context does not match the id used at registration time.
Common situations: Long-lived background goroutines surviving past scan teardown; SDK users inventing their own execution ids without registering dialers; races between execution cleanup and in-flight SMB/DCOM operations.
Related errors
- goimpacket: refusing to dial %s/%s without an executionId-bo
- authentication failed
- prompt not found (read cap reached)
- invalid address %q: %w
- grpc: refusing to dial without executionId
AI-assisted analysis of projectdiscovery/nuclei@265b3a3dec (2026-08-15).
Data as JSON: /api/errors/2abd7ad55a8a671e.
Report an issue: GitHub.