neondatabase/neon · error
process exited with
Error message
process exited with {status} What it means
compute_tools::swap::resize_swap runs `/usr/bin/sudo /neonvm/bin/resize-swap --once <size_bytes>` to grow the VM swap device before Postgres starts. This error means the child process ran but exited with a failure status AND the resize-swap binary still exists at /neonvm/bin/resize-swap (if the binary is gone, the failure is treated as 'not installed' and only warned about, because --once makes the script delete itself on success). The error is wrapped with the full command line, so the anyhow chain shows both the exit status and the invocation.
Solutions
- Run `/usr/bin/sudo /neonvm/bin/resize-swap --once <size>` manually with the same size to see the script's real error output (this Rust wrapper discards the child's stdout/stderr).
- Verify sudo is installed and allows running the script non-interactively (`sudo -n /neonvm/bin/resize-swap --once 1073741824`).
- Check that size_bytes is sane (non-zero, plausible multiple of KiB) at the call site that computes it.
- If you don't need swap resizing in your environment, remove or rename /neonvm/bin/resize-swap so the code takes the Ok(false) path and only warns.
- If the failure is acceptable operationally, catch/warn at the call site in compute startup instead of propagating it.
Example fix
// before
resize_swap(size_bytes)?; // aborts compute startup on resize-swap failure
// after
if let Err(e) = resize_swap(size_bytes) {
tracing::warn!("resize-swap failed, continuing without resize: {e:#}");
} Defensive patterns
Strategy: fallback
Validate before calling
// before calling compute startup / resize_swap
use std::path::Path;
let installed = Path::new("/neonvm/bin/resize-swap").try_exists().unwrap_or(false)
&& Path::new("/usr/bin/sudo").exists();
if !installed {
// resize-swap not present: skip instead of relying on the internal warn path
return Ok(());
} Type guard
fn swap_resize_available() -> bool {
std::path::Path::new("/neonvm/bin/resize-swap").exists()
&& std::path::Path::new("/usr/bin/sudo").exists()
} Try / catch
if let Err(e) = resize_swap(size_bytes) {
// swap sizing is an optimization; do not abort compute startup over it
tracing::warn!("resize-swap failed, continuing without resize: {e:#}");
} Prevention
- Pin a known-good VM image containing the resize-swap script you tested.
- Smoke-test `/usr/bin/sudo /neonvm/bin/resize-swap --once 1` in image CI so regressions surface at build time.
- Validate size_bytes (non-zero, KiB-aligned) before computing the swap target.
- In non-NeonVM environments, ensure the binary is absent so the built-in warn-only path applies.
When it happens
Trigger: Calling compute node startup (compute_ctl) in a NeonVM environment where resize-swap is present but fails: invalid size argument, sudo refusing to execute the script, missing CAP_SYS_ADMIN for swapon/swapoff, or the swap file/device being in a bad state. Only triggered when try_exists() on RESIZE_SWAP_BIN returns Ok(true) or errors; Ok(false) degrades to a warn.
Common situations: Custom or older VM images where /neonvm/bin/resize-swap exists but has a bug; sudoers configuration that blocks the command; running the compute container in an environment (plain docker, bare-metal dev box) where the binary path exists as a leftover file but the swap operations fail; size_bytes computed as 0 or overflowing the script's parser.
Related errors
- pg_ctl failed, exit code
- process exited with
- can't change stripe size from
- can't reduce shard count from
- cannot find 'blkno='
AI-assisted analysis of neondatabase/neon@8f60b04da4 (2026-08-16).
Data as JSON: /api/errors/11a69d5793fcb7e8.
Report an issue: GitHub.
Appendix: source
Thrown at compute_tools/src/swap.rs:33
//
// NOTE: resize-swap is not very clever. If present, --once MUST be the first arg.
let child_result = std::process::Command::new("/usr/bin/sudo")
.arg(RESIZE_SWAP_BIN)
.arg("--once")
.arg(size_bytes.to_string())
.spawn();
child_result
.context("spawn() failed")
.and_then(|mut child| child.wait().context("wait() failed"))
.and_then(|status| match status.success() {
true => Ok(()),
false => {
// The command failed. Maybe it was because the resize-swap file doesn't exist?
// The --once flag causes it to delete itself on success so we don't disable swap
// while postgres is running; maybe this is fine.
match Path::new(RESIZE_SWAP_BIN).try_exists() {
Err(_) | Ok(true) => Err(anyhow!("process exited with {status}")),
// The path doesn't exist; we're actually ok
Ok(false) => {
warn!("ignoring \"not found\" error from resize-swap to avoid swapoff while compute is running");
Ok(())
},
}
}
})
// wrap any prior error with the overall context that we couldn't run the command
.with_context(|| {
format!("could not run `/usr/bin/sudo {RESIZE_SWAP_BIN} --once {size_bytes}`")
})
}
View on GitHub (pinned to 8f60b04da4)