linera-io/linera-protocol · error
Failed to generate shard configs
Error message
Failed to generate shard configs
What it means
Panic when `generate_shard_configs(&num_shards, &host, &port, &metrics_port)` returns an error in `server edit-shards`. The helper parses `num_shards` as a NonZeroU16, builds a `%` pattern as wide as the num_shards string, and for each shard index substitutes the pattern once into host/port/metrics_port before parsing the ports as u16. The real causes are the inner contexts: 'Failed to parse the number of shards', 'Failed to decode port into an integers', or the metrics-port variant; the panic text is only the outer wrapper.
Source
Thrown at linera-service/src/server.rs:938
Persist::persist(&mut config)
.await
.expect("Unable to write committee description");
info!("Wrote committee config {}", committee.to_str().unwrap());
}
}
ServerCommand::EditShards {
server_config_path,
num_shards,
host,
port,
metrics_port,
} => {
let mut server_config =
persistent::File::<ValidatorServerConfig>::read(&server_config_path)
.expect("Failed to read server config");
let shards = generate_shard_configs(&num_shards, &host, &port, &metrics_port)
.expect("Failed to generate shard configs");
server_config.internal_network.shards = shards;
Persist::persist(&mut server_config)
.await
.expect("Failed to write updated server config");
}
}
}
fn generate_shard_configs(
num_shards: &str,
host: &str,
port: &str,
metrics_port: &Option<String>,
) -> anyhow::Result<Vec<ShardConfig>> {
let mut shards = Vec::new();
let len = num_shards.len();
let num_shards = num_shards
.parse::<NonZeroU16>()View on GitHub (pinned to 6c226ddcb3)
Solutions
- Pass a positive integer for num_shards, e.g. `4` (not 0, not empty, at most 65535).
- Make sure each substituted port value is an integer in 0..=65535, and that the `%` pattern width equals the number of digits in num_shards (num_shards `12` needs `%%` patterns yielding 01..12).
- Quote the --host/--port/--metrics-port arguments in shell so `%` and digits reach the CLI intact.
- Pre-validate the arguments in a wrapper script before invoking edit-shards.
Example fix
// before
let shards = generate_shard_configs(&num_shards, &host, &port, &metrics_port)
.expect("Failed to generate shard configs");
// after
let shards = generate_shard_configs(&num_shards, &host, &port, &metrics_port)
.with_context(|| format!("invalid shard spec: num_shards={num_shards} host={host} port={port}"))?; Defensive patterns
Strategy: type-guard
Validate before calling
let n = num_shards.parse::<NonZeroU16>().context("num_shards must be a non-zero integer <= 65535")?;
let pattern = "%".repeat(num_shards.len());
for i in 1..=u16::from(n) {
let index = format!("{i:0width$}", width = num_shards.len());
port.replacen(&pattern, &index, 1).parse::<u16>()
.with_context(|| format!("port for shard {index} is not a valid u16"))?;
if let Some(mp) = metrics_port.as_ref() {
mp.replacen(&pattern, &index, 1).parse::<u16>()
.with_context(|| format!("metrics_port for shard {index} is not a valid u16"))?;
}
} Type guard
fn valid_shard_specs(num_shards: &str, port: &str, metrics_port: Option<&str>) -> bool {
let Ok(n) = num_shards.parse::<NonZeroU16>() else { return false };
let pattern = "%".repeat(num_shards.len());
(1..=u16::from(n)).all(|i| {
let index = format!("{i:0width$}", width = num_shards.len());
port.replacen(&pattern, &index, 1).parse::<u16>().is_ok()
&& metrics_port
.map_or(true, |p| p.replacen(&pattern, &index, 1).parse::<u16>().is_ok())
})
} Try / catch
let shards = match generate_shard_configs(&num_shards, &host, &port, &metrics_port) {
Ok(shards) => shards,
Err(err) => {
eprintln!("error: failed to generate shard configs: {err:#}");
std::process::exit(1);
}
}; Prevention
- Quote --host/--port/--metrics-port arguments so `%` reaches the CLI intact.
- Keep the `%` pattern width equal to the digit count of num_shards (num_shards `12` needs `%%` patterns).
- Sanity-check the substitution in shell first, e.g. `echo "95%%" | sed 's/%%/01/'`.
- Reject 0, empty, and non-numeric num_shards in wrapper scripts before calling edit-shards.
When it happens
Trigger: num_shards given as 0, empty, non-numeric, or above 65535; a port string whose substituted value does not parse as u16 (letters left in the string, or a value above 65535); `--metrics-port` with an unparseable substituted value; a `%` pattern whose width does not match the num_shards digit count so substitution leaves stray `%` characters in the port.
Common situations: Shell mangling of unquoted `%` arguments; copy-pasted CLI templates where the pattern width no longer matches num_shards; configs migrated from scripts that used a different shard-numbering convention.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- Unable to read validator options file
- owner should be different from spender
- Only allowed options are grpc and grpcs
- Invalid address value: {s}
- Failed to obtain a port
AI-assisted analysis of linera-io/linera-protocol@6c226ddcb3 (2026-08-22).
Data as JSON: /api/errors/6158cda6705b18e5.
Report an issue: GitHub.