{"record":{"id":"935789626b7f4a57","repo":"wavetermdev/waveterm","slug":"procinfo-createtoolhelp32snapshot-w","errorCode":null,"errorMessage":"procinfo: CreateToolhelp32Snapshot: %w","messagePattern":"procinfo: CreateToolhelp32Snapshot: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/util/procinfo/procinfo_windows.go","lineNumber":49,"sourceCode":"}\n\n// snapInfo holds the data collected in a single pass of CreateToolhelp32Snapshot.\ntype snapInfo struct {\n\tppid       uint32\n\tnumThreads uint32\n\texeName    string\n}\n\n// windowsSnapshot is the concrete type returned by MakeGlobalSnapshot on Windows.\ntype windowsSnapshot struct {\n\tprocs map[int32]*snapInfo\n}\n\n// MakeGlobalSnapshot enumerates all processes once via CreateToolhelp32Snapshot.\nfunc MakeGlobalSnapshot() (any, error) {\n\tsnap, err := windows.CreateToolhelp32Snapshot(windows.TH32CS_SNAPPROCESS, 0)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"procinfo: CreateToolhelp32Snapshot: %w\", err)\n\t}\n\tdefer windows.CloseHandle(snap)\n\n\tprocs := make(map[int32]*snapInfo)\n\n\tvar entry windows.ProcessEntry32\n\tentry.Size = uint32(unsafe.Sizeof(entry))\n\n\tif err := windows.Process32First(snap, &entry); err != nil {\n\t\treturn nil, fmt.Errorf(\"procinfo: Process32First: %w\", err)\n\t}\n\tfor {\n\t\tpid := int32(entry.ProcessID)\n\t\tprocs[pid] = &snapInfo{\n\t\t\tppid:       entry.ParentProcessID,\n\t\t\tnumThreads: entry.Threads,\n\t\t\texeName:    windows.UTF16ToString(entry.ExeFile[:]),\n\t\t}","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/util/procinfo/procinfo_windows.go#L31-L67","documentation":"MakeGlobalSnapshot opens a Win32 toolhelp snapshot of all processes via windows.CreateToolhelp32Snapshot; when the syscall fails this error wraps the underlying windows error. Without a snapshot no process data (ppid, threads, exe name) can be enumerated.","triggerScenarios":"Calling MakeGlobalSnapshot when CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0) fails — typically ERROR_ACCESS_DENIED from restrictive security software/policies, or when the calling process lacks sufficient privileges in hardened environments.","commonSituations":"Running under service accounts with stripped SeDebugPrivilege in locked-down environments; antivirus/EDR blocking toolhelp snapshots; extremely rare kernel resource exhaustion during process creation/destruction storms.","solutions":["Read the wrapped %w error with errors.Is to identify the specific win32 error code","Retry the call — transient failures can occur during heavy process create/destroy activity","Run the process with sufficient privileges or adjust EDR/AV policy blocking snapshots","Fall back to enumerating /proc-like data via other APIs (e.g. EnumProcesses) if snapshots are blocked"],"exampleFix":"// before\nsnap, err := procinfo.MakeGlobalSnapshot()\nif err != nil {\n\treturn err\n}\n// after\nsnap, err := procinfo.MakeGlobalSnapshot()\nif err != nil {\n\tlog.Printf(\"snapshot failed: %v; retrying once\", err)\n\tsnap, err = procinfo.MakeGlobalSnapshot()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"cannot enumerate processes: %w\", err)\n\t}\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"snap, err := procinfo.MakeGlobalSnapshot()\nif err != nil {\n\tvar sysErr syscall.Errno\n\tif errors.As(err, &sysErr) && sysErr == windows.ERROR_ACCESS_DENIED {\n\t\treturn fmt.Errorf(\"insufficient privileges to snapshot processes: %w\", err)\n\t}\n\ttime.Sleep(50 * time.Millisecond)\n\tsnap, err = procinfo.MakeGlobalSnapshot()\n}\nif err != nil { return err }","preventionTips":["Run with adequate privileges in hardened/EDR-heavy environments","Retry once on failure — snapshot creation is occasionally transient","Log the wrapped win32 error code for diagnosis","Avoid calling during extreme process churn if possible"],"tags":["windows","syscall","process-enumeration"],"backgroundTag":"toolhelp-snapshot-failed","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}