linera-io/linera-protocol · error · anyhow

Child process {self:?} already exited with status: {status}

Error message

Child process {self:?} already exited with status: {status}

What it means

Raised by `ChildExt::ensure_is_running` (linera-service util.rs) when the tokio child process wrapped by the test harness (e.g. a linera-service node, faucet, or proxy started for a test) has already terminated — `try_wait()` returns `Some(status)`. It is the harness's crash detector: any later operation on the dead child reports this with the child's debug representation and exit status. The real failure happened earlier (the child's own crash), so this error is a symptom, not the root cause.

Source

Thrown at linera-service/src/util.rs:35

use linera_base::data_types::TimeDelta;
pub use linera_client::util::*;
use tracing::debug;

/// Default pause, in seconds, inserted after `linera service` commands in readme e2e tests.
pub static DEFAULT_PAUSE_AFTER_LINERA_SERVICE_SECS: &str = "3";
/// Default pause, in seconds, inserted after GraphQL mutations in readme e2e tests.
pub static DEFAULT_PAUSE_AFTER_GQL_MUTATIONS_SECS: &str = "3";

/// Extension trait for [`tokio::process::Child`].
pub trait ChildExt: std::fmt::Debug {
    /// Ensures the child process is still running, returning an error if it has exited.
    fn ensure_is_running(&mut self) -> Result<()>;
}

impl ChildExt for tokio::process::Child {
    fn ensure_is_running(&mut self) -> Result<()> {
        if let Some(status) = self.try_wait().context("try_wait child process")? {
            bail!("Child process {self:?} already exited with status: {status}");
        }
        debug!("Child process {self:?} is running as expected.");
        Ok(())
    }
}

/// Reads and deserializes a JSON value from the file at the given path.
pub fn read_json<T: serde::de::DeserializeOwned>(path: impl Into<std::path::PathBuf>) -> Result<T> {
    Ok(serde_json::from_reader(fs_err::File::open(path)?)?)
}

/// Expands to the name of the current test function.
#[cfg(with_testing)]
#[macro_export]
macro_rules! test_name {
    () => {
        stdext::function_name!()
            .strip_suffix("::{{closure}}")

View on GitHub (pinned to 6c226ddcb3)

Solutions

  1. Look at the earlier output/stderr of the child process in the test logs — the actual crash reason is printed before this error
  2. Reproduce by running the same linera-service command manually with the same arguments
  3. Check for port conflicts between concurrently running tests (give each test unique ports)
  4. Make the test fail fast on the first child error instead of issuing further operations against a dead child
Defensive patterns

Strategy: validation

Validate before calling

// Rust: check the child is alive before issuing harness operations
use linera_service::util::ChildExt;

child.ensure_is_running()?; // fails fast with the exit status instead of a confusing later error
// or, manually:
if let Some(status) = child.try_wait()? {
    anyhow::bail!("node exited early with {status}; inspect its stderr above");
}

Try / catch

// Treat as symptom: surface the crash, do not retry operations against a dead child
let result = operation(&mut child).await;
if let Err(e) = &result {
    if e.to_string().contains("already exited with status") {
        // fail the test now; the root cause is in the child's earlier stderr
        return Err(anyhow::anyhow!("child crashed earlier: {e}").context("see child stderr"));
    }
}

Prevention

When it happens

Trigger: Invoking any harness operation (query_node, process spawn, faucet call, etc.) that calls `ensure_is_running` after the wrapped child has exited — e.g. the node binary panicked at startup, exited due to bad arguments, hit a port conflict, or was killed by the OS/OOM.

Common situations: Parallel e2e tests racing for the same ports so one node exits immediately; a faucet/node failing on a missing genesis file; CI runners killing memory-heavy linera-service children; tests continuing after a child crash instead of aborting at the first failure.

Related errors


AI-assisted analysis of linera-io/linera-protocol@6c226ddcb3 (2026-08-22). Data as JSON: /api/errors/9b5a1023e1812cda. Report an issue: GitHub.