linera-io/linera-protocol · error · anyhow
Failed to start faucet
Error message
Failed to start faucet
What it means
`run_faucet` spawns `linera faucet --port <p> --amount <a> --storage-path <tmp>/faucet_storage.sqlite [chain_id]` and polls `GET http://localhost:{port}/` up to 10 times with 0..9s sleeps. Any successful HTTP response counts as started; the bail means the faucet never answered — it crashed at startup or the port was unavailable. Heavy users include the e2e faucet/reconfiguration tests.
Source
Thrown at linera-service/src/cli_wrappers/wallet.rs:717
"--storage-path".to_string(),
storage_path.to_string_lossy().to_string(),
]);
if let Some(chain_id) = chain_id {
command.arg(chain_id.to_string());
}
let child = command.spawn_into()?;
let client = reqwest_client();
for i in 0..10 {
linera_base::time::timer::sleep(Duration::from_secs(i)).await;
let request = client.get(format!("http://localhost:{port}/")).send().await;
if request.is_ok() {
tracing::info!("Faucet has started");
return Ok(FaucetService::new(port, child, temp_dir));
} else {
tracing::debug!("Waiting for faucet to start");
}
}
bail!("Failed to start faucet");
}
/// Runs `linera local-balance`.
pub async fn local_balance(&self, account: Account) -> Result<Amount> {
let stdout = self
.command()
.await?
.arg("local-balance")
.arg(account.to_string())
.spawn_and_wait_for_stdout()
.await?;
let amount = stdout
.trim()
.parse()
.context("error while parsing the result of `linera local-balance`")?;
Ok(amount)
}
View on GitHub (pinned to 6c226ddcb3)
Solutions
- Give the faucet its own port (do not reuse the node-service port, especially the 8080 default)
- Check for and kill stale listeners: `lsof -i :<port>`
- Run `linera faucet --port <p> --amount <a>` manually with the same args to see its startup error
- Ensure the faucet's chain exists and is funded before starting it, then retry
Example fix
// before let service = client.run_node_service_with_options(Some(8080), ...).await?; let faucet = client.run_faucet(None /* 8080 again! */, ...).await?; // port collision // after let service = client.run_node_service_with_options(Some(18080), ...).await?; let faucet = client.run_faucet(Some(18081), ...).await?;
Defensive patterns
Strategy: retry
Validate before calling
// Never share the default 8080 between faucet and node service. let faucet_port = linera_base::port::get_free_endpoint().await?.port().unwrap(); let faucet = client.run_faucet(Some(faucet_port), Some(chain_id), amount).await?;
Try / catch
match client.run_faucet(Some(port), Some(chain_id), amount).await {
Err(e) if e.to_string() == "Failed to start faucet" => {
// child died or port busy; check lsof, verify the chain is funded/synced, retry
ensure_port_free(port)?;
client.run_faucet(Some(port), Some(chain_id), amount).await
}
result => result,
} Prevention
- Assign the faucet a unique port; the default 8080 collides with node services in the same test
- Ensure the faucet's chain is created and funded before spawning the faucet
- Drop FaucetService handles in test teardown so children and their temp storage dirs are cleaned up
When it happens
Trigger: The faucet child fails to bind its port (default 8080, commonly colliding with a node service), exits because the given chain/amount config is invalid, or comes up slower than the ~45s polling budget.
Common situations: Starting faucet and node service both on the default 8080 in the same test; the faucet's chain not yet synced/registered; leftover faucet process holding the port; slow CI machines.
Related errors
- Failed to start node service
- Failed to start {nickname}
- failed to create SQLite database file: {database_url}, error
- failed to check SQLite database existence. file: {database_u
- Invalid options file format: \n {options_string}
AI-assisted analysis of linera-io/linera-protocol@6c226ddcb3 (2026-08-22).
Data as JSON: /api/errors/4d51457d68e5c9db.
Report an issue: GitHub.