FuelLabs/sway · error

Failed to execute ps command

Error message

Failed to execute ps command

What it means

forc-util's file locking serializes concurrent builds of the same package directory. When it inspects an existing lock file, is_pid_active checks the recorded PID by running `ps -p <pid>` (sysinfo is deliberately avoided due to a fuel.nix conflict, per the comment). This expect panics when the ps process itself cannot be spawned — a missing ps binary or a fork failure — not when the target process is gone.

Source

Thrown at forc-util/src/fs_locking.rs:50

    }

    /// Create a new PidFileLocking instance that is shared between the LSP and any other process
    /// that may want to update the file and needs to wait for the LSP to finish (like forc-fmt)
    pub fn lsp<X: AsRef<Path>>(filename: X) -> PidFileLocking {
        Self::new(filename, ".lsp-locks", "lock")
    }

    /// Checks if the given pid is active
    #[cfg(not(target_os = "windows"))]
    fn is_pid_active(pid: usize) -> bool {
        // Not using sysinfo here because it has compatibility issues with fuel.nix
        // https://github.com/FuelLabs/fuel.nix/issues/64
        use std::process::Command;
        let output = Command::new("ps")
            .arg("-p")
            .arg(pid.to_string())
            .output()
            .expect("Failed to execute ps command");

        let output_str = String::from_utf8_lossy(&output.stdout);
        output_str.contains(&format!("{pid} "))
    }

    #[cfg(target_os = "windows")]
    fn is_pid_active(pid: usize) -> bool {
        // Not using sysinfo here because it has compatibility issues with fuel.nix
        // https://github.com/FuelLabs/fuel.nix/issues/64
        use std::process::Command;
        let output = Command::new("tasklist")
            .arg("/FI")
            .arg(format!("PID eq {}", pid))
            .output()
            .expect("Failed to execute tasklist command");

        let output_str = String::from_utf8_lossy(&output.stdout);
        // Check if the output contains the PID, indicating the process is active

View on GitHub (pinned to 47e5e902fa)

Solutions

  1. Install procps in the image: `apt-get update && apt-get install -y procps` (Debian/Ubuntu) or the equivalent for the base image.
  2. Delete the stale lock file from the package's output directory (out/... .forc-lock) so no PID check is needed.
  3. Avoid sharing the build/output directory across containers that cannot see each other's PIDs.

Example fix

# before
FROM debian:bookworm-slim   # no ps installed; stale lock -> panic
# after
FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y procps && rm -rf /var/lib/apt/lists/*
Defensive patterns

Strategy: validation

Validate before calling

# entrypoint guard: ps must be spawnable before builds run
command -v ps >/dev/null 2>&1 || { echo "install procps (apt-get install -y procps)" >&2; exit 1; }

Prevention

When it happens

Trigger: A lock file exists in the package output directory (left by a previous/crashed build) and forc evaluates its staleness in an environment where /usr/bin/ps is absent: distroless/scratch/minimal containers, seccomp profiles blocking process spawn, or PID/resource exhaustion causing spawn failure.

Common situations: Running forc build in slim Docker images without procps installed; CI jobs on hand-rolled minimal images; a killed CI build leaving a lock file that the retry run then tries to validate.

Related errors


AI-assisted analysis of FuelLabs/sway@47e5e902fa (2026-08-16). Data as JSON: /api/errors/65518bdf7c9ce73a. Report an issue: GitHub.