{"record":{"id":"35332da96c30aabc","repo":"neondatabase/neon","slug":"process-exited-with-status","errorCode":null,"errorMessage":"process exited with {status}","messagePattern":"process exited with (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"compute_tools/src/disk_quota.rs","lineNumber":23,"sourceCode":"\n/// If size_bytes is 0, it disables the quota. Otherwise, it sets filesystem quota to size_bytes.\n/// `fs_mountpoint` should point to the mountpoint of the filesystem where the quota should be set.\n#[instrument]\npub fn set_disk_quota(size_bytes: u64, fs_mountpoint: &str) -> anyhow::Result<()> {\n    let size_kb = size_bytes / 1024;\n    // run `/neonvm/bin/set-disk-quota {size_kb} {mountpoint}`\n    let child_result = std::process::Command::new(\"/usr/bin/sudo\")\n        .arg(DISK_QUOTA_BIN)\n        .arg(size_kb.to_string())\n        .arg(fs_mountpoint)\n        .spawn();\n\n    child_result\n        .context(\"spawn() failed\")\n        .and_then(|mut child| child.wait().context(\"wait() failed\"))\n        .and_then(|status| match status.success() {\n            true => Ok(()),\n            false => Err(anyhow::anyhow!(\"process exited with {status}\")),\n        })\n        // wrap any prior error with the overall context that we couldn't run the command\n        .with_context(|| format!(\"could not run `/usr/bin/sudo {DISK_QUOTA_BIN}`\"))\n}\n","sourceCodeStart":5,"sourceCodeEnd":28,"githubUrl":"https://github.com/neondatabase/neon/blob/8f60b04da47ffefe0e52bda2440134b42874eb75/compute_tools/src/disk_quota.rs#L5-L28","documentation":"compute_ctl enforces the disk quota by shelling out to `/usr/bin/sudo /neonvm/bin/set-disk-quota {size_kb} {mountpoint}`. The child process ran but exited non-zero; the anyhow context wrapper adds 'could not run ...' so the chain reads context -> 'process exited with {status}'. The exit status (code/signal) and which prerequisite failed (sudo policy, missing binary, bad mountpoint) must be read from the chain.","triggerScenarios":"set-disk-quota exits non-zero: the binary /neonvm/bin/set-disk-quota is missing or not executable; sudoers does not allow NOPASSWD execution for the compute_ctl user; the mountpoint argument does not match a mounted filesystem; size_kb rejected as invalid.","commonSituations":"Running compute_ctl outside a NeonVM image (plain VM/container without the quota tool); base image changes that moved the binary; sudoers hardening removing the whitelisted rule; wrong fs_mountpoint after mount-layout changes; smoke/dev environments.","solutions":["Reproduce manually: /usr/bin/sudo /neonvm/bin/set-disk-quota <size_kb> <mount> and read the tool's own error","Verify /neonvm/bin/set-disk-quota exists and is executable in the image the compute runs in","Check sudoers grants the runtime user passwordless rights for exactly that command","Confirm the mountpoint passed matches an actual mount (cat /proc/mounts)"],"exampleFix":"# before: fails inside container without the NeonVM tool\n/usr/bin/sudo /neonvm/bin/set-disk-quota 1048576 /var/lib/postgresql\n# after (sudoers)\nCmnd_Alias QUOTA = /neonvm/bin/set-disk-quota\ncompute_ctl_user ALL=(root) NOPASSWD: QUOTA","handlingStrategy":"validation","validationCode":"// Preconditions before spawning sudo\nif !std::path::Path::new(DISK_QUOTA_BIN).exists() {\n    anyhow::bail!(\"{DISK_QUOTA_BIN} not present; disk quota cannot be enforced\");\n}\nif !mountpoint_mounted(fs_mountpoint) { anyhow::bail!(\"{fs_mountpoint} is not a mountpoint\"); }","typeGuard":"fn disk_quota_tooling_ready() -> bool {\n    std::path::Path::new(\"/usr/bin/sudo\").exists() && std::path::Path::new(DISK_QUOTA_BIN).exists()\n}","tryCatchPattern":"// Read the ExitStatus from the chain to distinguish causes\nlet out = Command::new(\"/usr/bin/sudo\").arg(DISK_QUOTA_BIN).args([size, mount]).output()?;\nif !out.status.success() {\n    let reason = out.status.code().map(|c| format!(\"exit {c}\")).unwrap_or_else(|| \"signal\".into());\n    return Err(anyhow!(\"set-disk-quota failed ({reason}): {}\", String::from_utf8_lossy(&out.stderr)));\n}","preventionTips":["Ship set-disk-quota in the image and add an entrypoint assertion that it exists and runs via sudo","Keep the sudoers rule pinned to the exact binary path and arguments; test it in image CI","Log stdout/stderr of the child, not just the exit status, when wrapping this error"],"tags":["rust","compute-ctl","disk-quota","sudo","subprocess","deployment"],"backgroundTag":"subprocess-exit-nonzero","analyzedSha":"8f60b04da47ffefe0e52bda2440134b42874eb75","analyzedAt":"2026-08-16T23:39:28.135Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}