xai-org/grok-build · error
process group setup failed: {e}
Error message
process group setup failed: {e} What it means
After spawning the helper, run_capped creates a process group via xai_grok_tools::util::ProcessGroup::new so the timeout path can kill the whole tree. If group creation fails this error is thrown and the operation aborts.
Source
Thrown at crates/codegen/xai-grok-shell/src/auth/auth_provider.rs:293
///
/// On timeout the child's entire process group is killed. The helper is a group
/// leader (`detach_command`'s `setsid`), so a compound `sh -c` helper's
/// grandchildren -- and the `GROK_AUTH_PROVIDER_*` credentials in their env --
/// do not outlive the reported timeout; `kill_on_drop` alone would reap only the
/// direct child.
async fn run_capped(
cmd: &mut tokio::process::Command,
timeout: std::time::Duration,
) -> anyhow::Result<std::process::Output> {
#[allow(clippy::disallowed_methods)] // killed at the timeout this call reports
let mut child = cmd
.spawn()
.map_err(|e| anyhow::anyhow!("command failed to start: {e}"))?;
// Enroll the child's process group so the timeout path can tear down the
// whole tree. Best-effort: if enrollment fails, `kill_on_drop` still reaps
// the direct child.
let mut group = xai_grok_tools::util::ProcessGroup::new()
.map_err(|e| anyhow::anyhow!("process group setup failed: {e}"))?;
if let Err(e) = group.attach(&child) {
tracing::debug!(error = %e, "auth provider: could not enroll helper process group");
}
let stdout = child.stdout.take().expect("stdout is piped");
let stderr = child.stderr.take().expect("stderr is piped");
let mut out_buf = Vec::new();
let mut err_buf = Vec::new();
// One extra stdout byte so an over-cap write is detectable, not truncated.
// The stderr read is advisory (it only feeds the failure log), so only
// stdout governs the mint.
let capture = async {
let (out_res, err_res) = tokio::join!(
read_capped(stdout, PROVIDER_STDOUT_CAP_BYTES + 1, &mut out_buf),
read_capped(stderr, PROVIDER_STDERR_CAP_BYTES, &mut err_buf),
);
if let Err(e) = err_res {
tracing::debug!(error = %e, "auth provider: stderr capture failed (advisory)");View on GitHub (pinned to bc7f02eddd)
Solutions
- Check system process limits (ulimit -u) and raise if exhausted
- Review container/seccomp policy to allow setpgid/setrlimit syscalls
- Retry after load subsides if it was a transient resource limit
Defensive patterns
Strategy: try-catch
Try / catch
match mint_provider_token().await {
Err(e) if e.to_string().contains("process group setup failed") => {
eprintln!("environment blocks process-group creation: {e}");
// fall back to a non-grouped execution path or surface to ops
}
other => other?,
} Prevention
- Verify seccomp/sandbox profiles allow setpgid/setrlimit
- Monitor RLIMIT_NPROC under load
- Test auth flows inside the actual container hardening config before deploy
When it happens
Trigger: ProcessGroup::new failing — typically setpgid/setsid resource or permission issues, e.g. hitting the process/thread limit (RLIMIT_NPROC) or running in a restricted sandbox that forbids the syscall.
Common situations: Hardened containers/seccomp profiles blocking setpgid, exhausted PID limits under heavy load, or security software blocking process-group creation.
Related errors
- refusing degenerate process-group id {pid} (0 = own group, 1
- process-group id {pid} exceeds i32::MAX; cannot be used with
- refusing to killpg the caller's own process group ({pid})
- git {shown} failed in {}: {}
- {label} exited with {}: {}
AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31).
Data as JSON: /api/errors/9472d87aa1515475.
Report an issue: GitHub.