wavetermdev/waveterm · error
invalid pgid returned: %d
Error message
invalid pgid returned: %d
What it means
After a successful GetProcessGroupId call, GetPGID sanity-checks that the returned pgid is positive. A zero or negative value would be nonsensical, so it is rejected with this error — indicating an unexpected kernel/utility-layer response.
Source
Thrown at pkg/jobmanager/jobcmd.go:132
defer jm.lock.Unlock()
return jm.cmd, jm.cmdPty
}
func (jm *JobCmd) GetPGID() (int, error) {
jm.lock.Lock()
defer jm.lock.Unlock()
if jm.cmd == nil || jm.cmd.Process == nil {
return 0, fmt.Errorf("no active process")
}
if jm.processExited {
return 0, fmt.Errorf("process already exited")
}
pgid, err := unixutil.GetProcessGroupId(jm.cmd.Process.Pid)
if err != nil {
return 0, fmt.Errorf("failed to get pgid: %w", err)
}
if pgid <= 0 {
return 0, fmt.Errorf("invalid pgid returned: %d", pgid)
}
return pgid, nil
}
func (jm *JobCmd) GetExitInfo() (bool, *wshrpc.CommandJobCmdExitedData) {
jm.lock.Lock()
defer jm.lock.Unlock()
if !jm.processExited {
return false, nil
}
exitData := &wshrpc.CommandJobCmdExitedData{
JobId: WshCmdJobManager.JobId,
ExitCode: jm.exitCode,
ExitSignal: jm.exitSignal,
ExitTs: jm.exitTs,
}
if jm.exitErr != nil {
exitData.ExitErr = jm.exitErr.Error()View on GitHub (pinned to a4447c1563)
Solutions
- Inspect the unixutil.GetProcessGroupId implementation for the current platform and fix the return-value handling.
- Log the pid/pgid pair and report a bug if a real kernel returned pgid <= 0.
- Fall back to treating the process's pid as its group leader when the lookup misbehaves.
- Add a unit test asserting positive pgid on each supported platform.
Example fix
// before
pgid, err := unixutil.GetProcessGroupId(pid)
return pgid, err
// after
pgid, err := unixutil.GetProcessGroupId(pid)
if pgid <= 0 {
return 0, fmt.Errorf("invalid pgid returned: %d", pgid)
}
return pgid, err Defensive patterns
Strategy: type-guard
Validate before calling
func sanePGID(pgid int) bool { return pgid > 0 } Type guard
func isValidPGID(pgid int, ok bool) bool {
return ok && pgid > 0
} Try / catch
pgid, err := jobCmd.GetPGID()
if err != nil {
if strings.Contains(err.Error(), "invalid pgid returned") {
// platform bug: fall back to treating pid as pgid
return jobCmd.PID()
}
return err
} Prevention
- Unit-test unixutil.GetProcessGroupId on every supported platform
- Don't stub the pgid lookup with zero-returning mocks in tests
- Log pid and pgid together to catch platform regressions early
When it happens
Trigger: unixutil.GetProcessGroupId returns a non-positive value despite reporting success — essentially only from a broken platform implementation or an unexpected syscall result.
Common situations: Porting to a new OS/platform where the pgid lookup shim returns 0 on success; a stubbed or mocked unixutil in tests.
Related errors
- failed to get pgid: %w
- no active process
- job manager only supported on unix systems, not %s
- failed to daemonize: %w
- failed to setsid: %w
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/a6832b172fc34af8.
Report an issue: GitHub.