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 activeView on GitHub (pinned to 47e5e902fa)
Solutions
- Install procps in the image: `apt-get update && apt-get install -y procps` (Debian/Ubuntu) or the equivalent for the base image.
- Delete the stale lock file from the package's output directory (out/... .forc-lock) so no PID check is needed.
- 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
- Base build images on debian-slim + procps rather than distroless/scratch for forc workloads.
- Clean lock files (out/**/.forc-lock) after a killed build so no PID check is attempted.
- Don't share output directories between forc processes in different PID namespaces.
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
- Failed to execute tasklist command
- unable to find the user home directory
- Failed to execute ps command
- Could not get plugin description.
- Could not get homedir
AI-assisted analysis of FuelLabs/sway@47e5e902fa (2026-08-16).
Data as JSON: /api/errors/65518bdf7c9ce73a.
Report an issue: GitHub.