neondatabase/neon · error

process exited with {status}

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.

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)

Solutions

  1. 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).
  2. Verify sudo is installed and allows running the script non-interactively (`sudo -n /neonvm/bin/resize-swap --once 1073741824`).
  3. Check that size_bytes is sane (non-zero, plausible multiple of KiB) at the call site that computes it.
  4. 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.
  5. 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

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


AI-assisted analysis of neondatabase/neon@8f60b04da4 (2026-08-16). Data as JSON: /api/errors/11a69d5793fcb7e8. Report an issue: GitHub.