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

  1. Keep only one `tcp:host:port` entry and delete the duplicate
  2. 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

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


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