{"record":{"id":"e25097e7e66f23dc","repo":"wavetermdev/waveterm","slug":"invalid-pid-d","errorCode":null,"errorMessage":"invalid pid: %d","messagePattern":"invalid pid: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/wshrpc/wshremote/wshremote.go","lineNumber":143,"sourceCode":"\t}\n\timpl.Log(\"created symlink %s -> %s\\n\", symlinkPath, impl.SockName)\n\treturn nil\n}\n\nfunc (impl *ServerImpl) getWshPath() (string, error) {\n\tif impl.IsLocal {\n\t\treturn filepath.Join(wavebase.GetWaveDataDir(), \"bin\", \"wsh\"), nil\n\t}\n\twshPath, err := wavebase.ExpandHomeDir(\"~/.waveterm/bin/wsh\")\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"cannot expand wsh path: %w\", err)\n\t}\n\treturn wshPath, nil\n}\n\nfunc (impl *ServerImpl) BadgeWatchPidCommand(ctx context.Context, data wshrpc.CommandBadgeWatchPidData) error {\n\tif data.Pid <= 0 {\n\t\treturn fmt.Errorf(\"invalid pid: %d\", data.Pid)\n\t}\n\tif data.ORef.IsEmpty() {\n\t\treturn fmt.Errorf(\"oref is required\")\n\t}\n\tif data.BadgeId == \"\" {\n\t\treturn fmt.Errorf(\"badgeid is required\")\n\t}\n\tgo func() {\n\t\tdefer func() {\n\t\t\tpanichandler.PanicHandler(\"BadgeWatchPidCommand\", recover())\n\t\t}()\n\t\tfor {\n\t\t\ttime.Sleep(time.Second)\n\t\t\tif unixutil.IsPidRunning(data.Pid) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\torefStr := data.ORef.String()\n\t\t\tevent := wps.WaveEvent{","sourceCodeStart":125,"sourceCodeEnd":161,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/wshrpc/wshremote/wshremote.go#L125-L161","documentation":"Returned when the pid in an RPC request is invalid (zero or negative), identified by the %d value in the message.","triggerScenarios":"Calling BadgeWatchPidCommand with CommandBadgeWatchPidData.Pid == 0 or negative — typically an uninitialized struct or a failed process lookup upstream.","commonSituations":"Frontend sends badge data before the process actually spawned; a lookup returned (-1 or 0) on process-exit and the caller forwards it anyway.","solutions":["Ensure the process was successfully started and capture its real PID before watching","Skip/stop the badge watch when the process has exited instead of calling with 0/-1","Validate pid > 0 in the caller before issuing the RPC"],"exampleFix":"// before\nwshrpc.BadgeWatchPidCommand(ctx, wshrpc.CommandBadgeWatchPidData{Pid: proc.Pid})\n// after\nif proc.Pid > 0 {\n    wshrpc.BadgeWatchPidCommand(ctx, wshrpc.CommandBadgeWatchPidData{Pid: proc.Pid})\n}","handlingStrategy":"validation","validationCode":"if data.Pid <= 0 {\n    return fmt.Errorf(\"refusing to watch badge: pid %d invalid\", data.Pid)\n}","typeGuard":null,"tryCatchPattern":"if err := BadgeWatchPidCommand(ctx, data); err != nil {\n    if strings.Contains(err.Error(), \"invalid pid\") {\n        return nil // skip badge watch for dead/unspawned process\n    }\n    return err\n}","preventionTips":["Only call after confirming the process spawned with pid > 0","Stop badge watches on process exit instead of passing 0/-1","Validate RPC payloads at the sender side"],"tags":["go","validation","rpc"],"backgroundTag":"invalid-argument","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}