{"record":{"id":"8140f738807880c4","repo":"wavetermdev/waveterm","slug":"procinfo-parse-pid-w","errorCode":null,"errorMessage":"procinfo: parse pid: %w","messagePattern":"procinfo: parse pid: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/util/procinfo/procinfo_linux.go","lineNumber":90,"sourceCode":"\tcomm := s[lp+1 : rp]\n\trest := strings.Fields(s[rp+1:])\n\n\t// rest[0] = field 3 (state), rest[1] = field 4 (ppid), ...\n\t// Fields after comm are numbered starting at 3, so rest[i] = field (i+3).\n\t// We need:\n\t//   rest[0]  = field  3  state\n\t//   rest[1]  = field  4  ppid\n\t//   rest[11] = field 14  utime\n\t//   rest[12] = field 15  stime\n\t//   rest[17] = field 20  num_threads\n\t//   rest[21] = field 24  rss (pages)\n\tif len(rest) < 22 {\n\t\treturn nil, fmt.Errorf(\"procinfo: too few fields in stat for pid %d\", pid)\n\t}\n\n\tparsedPid, err := strconv.ParseInt(pidStr, 10, 32)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"procinfo: parse pid: %w\", err)\n\t}\n\n\tstatusChar := rest[0]\n\tstatus, ok := LinuxStatStatus[statusChar]\n\tif !ok {\n\t\tstatus = \"unknown\"\n\t}\n\n\tinfo := &ProcInfo{\n\t\tPid:        int32(parsedPid),\n\t\tCommand:    comm,\n\t\tStatus:     status,\n\t\tCpuUser:    -1,\n\t\tCpuSys:     -1,\n\t\tVmRSS:      -1,\n\t\tNumThreads: -1,\n\t}\n","sourceCodeStart":72,"sourceCodeEnd":108,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/util/procinfo/procinfo_linux.go#L72-L108","documentation":"The leading pid field of /proc/<pid>/stat (text before the first '(') failed strconv.ParseInt. Since the kernel always writes a numeric pid here, this indicates the stat content is not a genuine procfs stat record or was truncated/garbled.","triggerScenarios":"Malformed or fixture-supplied stat data where the text before '(' is empty or non-numeric; corrupted procfs reads; a bind-mounted fake /proc directory.","commonSituations":"Unit tests with hand-written stat fixtures that omit the pid; containers with a non-procfs /proc; disk/kernel-level corruption (extremely rare).","solutions":["Inspect the actual file content: head -c 200 /proc/<pid>/stat — it must start with the pid followed by ' ('","If in tests, fix fixtures so stat lines begin with the numeric pid","Verify /proc is real procfs (mount -t proc) in the deployment environment","Retry the read if this occurred during heavy process churn"],"exampleFix":"// before\nparsedPid, err := strconv.ParseInt(pidStr, 10, 32)\nif err != nil {\n    return nil, fmt.Errorf(\"procinfo: parse pid: %w\", err)\n}\n// after: cross-check against the requested pid\nparsedPid, err := strconv.ParseInt(pidStr, 10, 32)\nif err != nil {\n    return nil, fmt.Errorf(\"procinfo: parse pid %q from stat: %w\", pidStr, err)\n}\nif int32(parsedPid) != pid {\n    return nil, fmt.Errorf(\"procinfo: stat pid mismatch: got %d want %d\", parsedPid, pid)\n}","handlingStrategy":"validation","validationCode":"// confirm the stat file starts with a numeric pid before deeper use\ndata, err := os.ReadFile(fmt.Sprintf(\"/proc/%d/stat\", pid))\nif err == nil {\n    idx := bytes.IndexByte(data, '(')\n    if idx <= 0 {\n        // no pid prefix: file is not a valid stat record\n    }\n}","typeGuard":null,"tryCatchPattern":"_, err := procinfo.GetProcInfo(ctx, nil, pid)\nif err != nil && strings.Contains(err.Error(), \"parse pid\") {\n    // stat content is not genuine procfs output; check /proc mounting and fixtures\n}","preventionTips":["Never bind-mount a fake directory over /proc in production containers","Keep stat fixtures realistic (start with the pid followed by ' (')","Verify with 'mount -t proc' that procfs is properly mounted","Log the offending pid string to diagnose corruption quickly"],"tags":["linux","procfs","parsing","strconv"],"backgroundTag":"proc-stat-malformed","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}