linera-io/linera-protocol · error · anyhow
Failed to start child server
Error message
Failed to start child server
What it means
Raised by `StorageService::wait_for_absence` (linera-storage-service child.rs) before spawning a child storage service. It polls `storage_service_check_absence` for the configured endpoint with increasing sleeps (1+2+...+9 ≈ 45s); if something is still serving on that endpoint after all attempts, it bails. In practice the endpoint is occupied by a leftover storage-service process (or previous child) that never shut down.
Source
Thrown at linera-storage-service/src/child.rs:49
}
fn command(&self) -> Command {
let mut command = Command::new(&self.binary);
command.args(["memory", "--endpoint", &self.endpoint]);
command.kill_on_drop(true);
command
}
/// Waits for the absence of the endpoint. If a child is terminated
/// then it might take time to wait for its absence.
async fn wait_for_absence(&self) -> Result<()> {
for i in 1..10 {
if storage_service_check_absence(&self.endpoint).await? {
return Ok(());
}
linera_base::time::timer::sleep(Duration::from_secs(i)).await;
}
bail!("Failed to start child server");
}
/// Starts the storage service child process and returns a guard that keeps it alive.
pub async fn run(&self) -> Result<StorageServiceGuard> {
self.wait_for_absence().await?;
let mut command = self.command();
let child = command.spawn_into()?;
let guard = StorageServiceGuard { _child: child };
// We iterate until the child is spawned and can be accessed.
// We add an additional waiting period to avoid problems.
for i in 1..10 {
let result = storage_service_check_validity(&self.endpoint).await;
if result.is_ok() {
return Ok(guard);
}
linera_base::time::timer::sleep(Duration::from_secs(i)).await;
}
bail!("Failed to start child server");View on GitHub (pinned to 6c226ddcb3)
Solutions
- Find and kill the process holding the endpoint (e.g. `lsof -i :7878` / `ss -ltnp` then kill, or `pkill -f linera-storage-service`)
- Use a unique endpoint/port per test run so services never collide
- If the previous child is legitimately still shutting down, allow more time or retry the run
- Make sure StorageServiceGuard values are dropped (or the test aborts cleanly) so children are killed between tests
Defensive patterns
Strategy: validation
Validate before calling
// Rust: verify the endpoint is free before StorageService::run
use tokio::net::TcpStream;
async fn endpoint_free(host: &str, port: u16) -> bool {
TcpStream::connect((host, port)).await.is_err() // connectable => something is serving
}
if !endpoint_free("127.0.0.1", port).await {
anyhow::bail!("endpoint {port} is occupied; kill the old storage service first");
} Try / catch
match storage_service.run().await {
Ok(guard) => guard,
Err(e) if e.to_string().contains("Failed to start child server") => {
// endpoint still occupied: kill the stale process, then retry once
let _ = std::process::Command::new("pkill")
.args(["-f", "linera-storage-service"])
.status();
storage_service.run().await?
}
Err(e) => return Err(e),
} Prevention
- Allocate a unique endpoint/port per test (e.g. from a port counter or ephemeral range)
- Ensure StorageServiceGuard is dropped at test end so the child is killed (kill_on_drop is set)
- Sweep for orphaned storage-service processes before a test suite starts
When it happens
Trigger: Calling `StorageService::run` on an endpoint where another storage service (from a previous test run, a crashed guard, or an orphaned process) is still listening and answering presence checks.
Common situations: Back-to-back e2e tests reusing the same endpoint without killing the previous service; a leaked child from a test that panicked before dropping its guard; a stale process from an aborted cargo test run.
Related errors
- test-log: RUST_LOG_SPAN_EVENTS must contain filters separate
- Expected an `ExecutionError`. Got: {self:#?}
- Expected an `ExecutionError`. Got: {chain_error:#?}
- failed to create SQLite database file: {database_url}, error
- failed to check SQLite database existence. file: {database_u
AI-assisted analysis of linera-io/linera-protocol@6c226ddcb3 (2026-08-22).
Data as JSON: /api/errors/c62837761b619847.
Report an issue: GitHub.