linera-io/linera-protocol · error · anyhow
The uri has already been assigned
Error message
The uri has already been assigned
What it means
Raised while parsing a `scylladb:` storage configuration in `StorageConfig::from_str` (linera-storage-runtime, scylladb feature). The parser loops over the segments and assigns the URI from the (single) `tcp` entry; encountering a second `tcp`-prefixed entry means the URI was already set, which is rejected. Correct form: `scylladb:[tcp:host:port:]table_<namespace>` with at most one tcp entry (defaults to localhost:9042).
Source
Thrown at linera-storage-runtime/src/storage_config.rs:199
let parse_error: &'static str = "Correct format is tcp:db_hostname:port.";
if !s.is_empty() {
let mut parts = s.split(':');
while let Some(part) = parts.next() {
match part {
"tcp" => {
let address = parts.next().ok_or_else(|| {
anyhow!("Failed to find address for {s}. {parse_error}")
})?;
let port_str = parts.next().ok_or_else(|| {
anyhow!("Failed to find port for {s}. {parse_error}")
})?;
let port = NonZeroU16::from_str(port_str).map_err(|_| {
anyhow!(
"Failed to find parse port {port_str} for {s}. {parse_error}",
)
})?;
if uri.is_some() {
bail!("The uri has already been assigned");
}
uri = Some(format!("{address}:{port}"));
}
_ if part.starts_with("table") => {
if namespace.is_some() {
bail!("The namespace has already been assigned");
}
namespace = Some(part.to_string());
}
_ => {
bail!("the entry \"{part}\" is not matching");
}
}
}
}
let uri = uri.unwrap_or_else(|| "localhost:9042".to_string());
let namespace = namespace.unwrap_or_else(|| DEFAULT_NAMESPACE.to_string());
let inner_storage_config = InnerStorageConfig::ScyllaDb { uri };View on GitHub (pinned to 6c226ddcb3)
Solutions
- Keep only one `tcp:host:port` entry and delete the duplicate
- If no custom host is needed, omit the tcp entry entirely — localhost:9042 is the default
Example fix
# before --storage scylladb:tcp:10.0.0.1:9042:tcp:10.0.0.2:9042:table_ns # after --storage scylladb:tcp:10.0.0.1:9042:table_ns
Defensive patterns
Strategy: validation
Validate before calling
// Rust: reject duplicate tcp entries in a scylladb string before FromStr
if let Some(rest) = storage_str.strip_prefix("scylladb:") {
let tcp_count = rest.split(':').filter(|p| *p == "tcp").count();
anyhow::ensure!(tcp_count <= 1, "scylladb config allows at most one tcp entry");
} Prevention
- Specify tcp:host:port at most once; omit it entirely to get localhost:9042
- Avoid concatenating config fragments that each carry their own tcp entry
When it happens
Trigger: Passing `scylladb:tcp:host1:9042:tcp:host2:9042:table_ns` — two tcp entries in one config string.
Common situations: Script loops or YAML anchors duplicating the tcp segment when composing the storage string; copy-paste merging two scylladb configs.
Related errors
- The namespace has already been assigned
- the entry "{part}" is not matching
- For DualRocksDbScyllaDb, the formatting has to be dualrocksd
- We should have one genesis config path and one optional name
- For Storage service, the formatting has to be service:endpoi
AI-assisted analysis of linera-io/linera-protocol@6c226ddcb3 (2026-08-22).
Data as JSON: /api/errors/6cf44aa82e451fd0.
Report an issue: GitHub.