{"record":{"id":"8781b6f0a7172e54","repo":"wavetermdev/waveterm","slug":"procinfo-getprocinfo-requires-a-snapshot-on-windo","errorCode":null,"errorMessage":"procinfo: GetProcInfo requires a snapshot on windows","messagePattern":"procinfo: GetProcInfo requires a snapshot on windows","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/util/procinfo/procinfo_windows.go","lineNumber":84,"sourceCode":"\t\t\texeName:    windows.UTF16ToString(entry.ExeFile[:]),\n\t\t}\n\t\tif err := windows.Process32Next(snap, &entry); err != nil {\n\t\t\tif errors.Is(err, windows.ERROR_NO_MORE_FILES) {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\treturn nil, fmt.Errorf(\"procinfo: Process32Next: %w\", err)\n\t\t}\n\t}\n\n\treturn &windowsSnapshot{procs: procs}, nil\n}\n\n// GetProcInfo returns a ProcInfo for the given pid.\n// snap must be a non-nil value returned by MakeGlobalSnapshot.\n// Returns nil, nil if the pid is not present in the snapshot.\nfunc GetProcInfo(_ context.Context, snap any, pid int32) (*ProcInfo, error) {\n\tif snap == nil {\n\t\treturn nil, fmt.Errorf(\"procinfo: GetProcInfo requires a snapshot on windows\")\n\t}\n\tws, ok := snap.(*windowsSnapshot)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"procinfo: invalid snapshot type\")\n\t}\n\tsi, found := ws.procs[pid]\n\tif !found {\n\t\treturn nil, ErrNotFound\n\t}\n\n\tinfo := &ProcInfo{\n\t\tPid:        pid,\n\t\tPpid:       int32(si.ppid),\n\t\tNumThreads: int32(si.numThreads),\n\t\tCommand:    si.exeName,\n\t\tCpuUser:    -1,\n\t\tCpuSys:     -1,\n\t\tVmRSS:      -1,","sourceCodeStart":66,"sourceCodeEnd":102,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/util/procinfo/procinfo_windows.go#L66-L102","documentation":"GetProcInfo on Windows requires the caller to pass the snapshot object returned by MakeGlobalSnapshot as the snap parameter; passing nil makes per-pid lookup impossible, so it returns this error immediately. The snapshot-based design avoids expensive per-pid opens on Windows.","triggerScenarios":"Calling GetProcInfo(ctx, nil, pid) — forgetting to create or retain the result of MakeGlobalSnapshot, or a variable that was never assigned because an earlier MakeGlobalSnapshot error path set it to nil.","commonSituations":"Ignoring the error from MakeGlobalSnapshot and using the nil snapshot anyway; struct fields holding the snapshot left uninitialized; passing nil in tests or when porting Linux code that has no snapshot parameter.","solutions":["Call MakeGlobalSnapshot first and pass its return value (not nil) as snap","Check the error from MakeGlobalSnapshot before using the snapshot","Cache the snapshot for the duration of the batch of GetProcInfo calls","On non-Windows platforms this error does not apply; guard platform-specific code paths"],"exampleFix":"// before\ninfo, _ := procinfo.GetProcInfo(ctx, cachedSnap, pid) // cachedSnap may be nil\n// after\nif cachedSnap == nil {\n\tcachedSnap, err = procinfo.MakeGlobalSnapshot()\n\tif err != nil {\n\t\treturn err\n\t}\n}\ninfo, err := procinfo.GetProcInfo(ctx, cachedSnap, pid)","handlingStrategy":"validation","validationCode":"if snap == nil {\n\ts, err := procinfo.MakeGlobalSnapshot()\n\tif err != nil { return err }\n\tsnap = s\n}","typeGuard":"func hasSnapshot(snap any) bool { return snap != nil }","tryCatchPattern":"info, err := procinfo.GetProcInfo(ctx, snap, pid)\nif err != nil {\n\tif strings.Contains(err.Error(), \"requires a snapshot\") {\n\t\treturn fmt.Errorf(\"call MakeGlobalSnapshot before GetProcInfo\")\n\t}\n\treturn err\n}","preventionTips":["Always check the error from MakeGlobalSnapshot before using its result","Store the snapshot in a struct field initialized at startup","Keep snapshot creation and usage adjacent in the same function","Remember Windows needs a snapshot; Linux code paths differ"],"tags":["windows","api-misuse","nil-argument"],"backgroundTag":"missing-snapshot-argument","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}