{"record":{"id":"babf2f4bcbb4ef6c","repo":"wavetermdev/waveterm","slug":"procinfo-invalid-snapshot-type","errorCode":null,"errorMessage":"procinfo: invalid snapshot type","messagePattern":"procinfo: invalid snapshot type","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/util/procinfo/procinfo_windows.go","lineNumber":88,"sourceCode":"\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,\n\t}\n\n\thandle, err := windows.OpenProcess(\n\t\twindows.PROCESS_QUERY_LIMITED_INFORMATION,","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/util/procinfo/procinfo_windows.go#L70-L106","documentation":"GetProcInfo type-asserts the snap parameter to *windowsSnapshot; if it is a non-nil value of any other type, this error is returned. It protects against passing foreign objects (e.g. a Linux snapshot type or a raw map) where the lookup would otherwise panic.","triggerScenarios":"Calling GetProcInfo with a non-nil snap that was not produced by MakeGlobalSnapshot on Windows — e.g. a snapshot from a different platform build, a mock in tests, or an `any` variable holding the wrong concrete type.","commonSituations":"Cross-platform code paths storing heterogeneous snapshot types in one `any` field; test doubles that don't match the internal snapshot type; refactors that swap snapshot implementations without updating call sites.","solutions":["Only pass values obtained from MakeGlobalSnapshot (same build/platform) into GetProcInfo","Check the wrapped type at the call site before invoking","Separate per-platform snapshot handling into typed code paths","In tests, use the real MakeGlobalSnapshot or generate a proper *windowsSnapshot"],"exampleFix":"// before\ninfo, err := procinfo.GetProcInfo(ctx, someGenericSnapshot, pid)\n// after\nif _, ok := someGenericSnapshot.(*procinfo.WindowsSnapshotLike); !ok && someGenericSnapshot != nil {\n\tsomeGenericSnapshot, err = procinfo.MakeGlobalSnapshot()\n\tif err != nil {\n\t\treturn err\n\t}\n}\ninfo, err := procinfo.GetProcInfo(ctx, someGenericSnapshot, pid)","handlingStrategy":"type-guard","validationCode":"if snap != nil {\n\tif _, ok := snap.(*procinfoSnapshot); !ok {\n\t\tsnap, err = procinfo.MakeGlobalSnapshot()\n\t}\n}","typeGuard":"func isWindowsSnapshot(snap any) bool {\n\t// snap is typed any; assert against the value returned by MakeGlobalSnapshot\n\treturn snap != nil && fmt.Sprintf(\"%T\", snap) == \"*procinfo.windowsSnapshot\"\n}","tryCatchPattern":"info, err := procinfo.GetProcInfo(ctx, snap, pid)\nif err != nil {\n\tif strings.Contains(err.Error(), \"invalid snapshot type\") {\n\t\treturn fmt.Errorf(\"snap must come from MakeGlobalSnapshot, got %T\", snap)\n\t}\n\tif errors.Is(err, procinfo.ErrNotFound) {\n\t\treturn nil // pid absent from snapshot\n\t}\n\treturn err\n}","preventionTips":["Only pass MakeGlobalSnapshot results into GetProcInfo","Keep per-platform snapshot types out of shared `any` fields when possible","Regenerate snapshots after platform switches or rebuilds","In tests, build mocks that mirror the real snapshot constructor"],"tags":["windows","type-assertion","api-misuse"],"backgroundTag":"invalid-snapshot-type","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}