{"record":{"id":"bfbf4e927e95c2e1","repo":"projectdiscovery/nuclei","slug":"dialers-not-initialized-for-s-bfbf4e","errorCode":null,"errorMessage":"dialers not initialized for %s","messagePattern":"dialers not initialized for (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/js/libs/smb/smb_private.go","lineNumber":27,"sourceCode":"\t\"github.com/praetorian-inc/fingerprintx/pkg/plugins\"\n\t\"github.com/praetorian-inc/fingerprintx/pkg/plugins/services/smb\"\n\t\"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate\"\n\tzgrabsmb \"github.com/zmap/zgrab2/lib/smb/smb\"\n)\n\ntype smbInfoDialFunc func(context.Context) (net.Conn, error)\n\n// ==== private helper functions/methods ====\n\n// collectSMBv2Metadata collects metadata for SMBv2 services.\n// @memo\nfunc collectSMBv2Metadata(ctx context.Context, executionId string, host string, port int, timeout time.Duration) (*plugins.ServiceSMB, error) {\n\tif timeout == 0 {\n\t\ttimeout = 5 * time.Second\n\t}\n\tdialer := protocolstate.GetDialersWithId(executionId)\n\tif dialer == nil {\n\t\treturn nil, fmt.Errorf(\"dialers not initialized for %s\", executionId)\n\t}\n\n\tconn, err := dialer.Fastdialer.Dial(ctx, \"tcp\", net.JoinHostPort(host, fmt.Sprintf(\"%d\", port)))\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer func() {\n\t\t_ = conn.Close()\n\t}()\n\n\tmetadata, err := smb.DetectSMBv2(conn, timeout)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn metadata, nil\n}\n\n// getSMBInfo","sourceCodeStart":9,"sourceCodeEnd":45,"githubUrl":"https://github.com/projectdiscovery/nuclei/blob/265b3a3dec374741614e342f813c10f8b38d2bb7/pkg/js/libs/smb/smb_private.go#L9-L45","documentation":"collectSMBv2Metadata (used for SMBv2/3 service fingerprinting) dials the target through protocolstate.GetDialersWithId(executionId); a nil dialer means the execution's network state was never initialized or was already disposed. It is the same state bug as in ConnectSMBInfoMode, reached through the metadata-collection path.","triggerScenarios":"SMB scanning hits a v2/v3-capable port and the code calls collectSMBv2Metadata while dialers for the executionId are absent — library misuse, uninitialized engine, or post-cleanup execution.","commonSituations":"SDK integrations that spawn their own goja runtimes; concurrent runs where one goroutine tears down shared state; tests that exercise fingerprinting without the dialer fixture.","solutions":["Initialize protocolstate before any SMB code runs (InitProtocolState with options)","Scope each run to its own execution lifecycle instead of reusing IDs across restarts","In tests, register dialers once in TestMain","If embedding, prefer the documented nuclei SDK entry points which set state up for you"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if protocolstate.GetDialersWithId(executionId) == nil {\n    return fmt.Errorf(\"engine not initialized; skip fingerprinting\")\n}","typeGuard":"func dialersReady(executionId string) bool {\n    return protocolstate.GetDialersWithId(executionId) != nil\n}","tryCatchPattern":"meta, err := collectSMBv2Metadata(ctx, executionId, host, port, timeout)\nif err != nil && strings.Contains(err.Error(), \"dialers not initialized\") {\n    return err // environment bug: fail fast rather than marking hosts dead\n}","preventionTips":["Do not invoke fingerprint helpers outside an initialized nuclei execution","Tear down protocol state only after all executions finish","Keep execution IDs stable within a run; never persist them across restarts"],"tags":["initialization","internal","network","smb","engine-state"],"backgroundTag":null,"analyzedSha":"265b3a3dec374741614e342f813c10f8b38d2bb7","analyzedAt":"2026-08-15T20:05:51.855Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}