linera-io/linera-protocol · error

Exporter URI should be valid

Error message

Exporter URI should be valid

What it means

In the same forward_notifications setup (linera-rpc/src/grpc/server.rs:527), each block-exporter address from the configured list is converted with Channel::from_shared and expected to be a valid URI. Any exporter address that is not a valid http/https URI - missing scheme, bad characters, empty string - panics the notification-forwarding task at startup of forwarding.

Source

Thrown at linera-rpc/src/grpc/server.rs:531

    async fn forward_notifications(
        nickname: String,
        proxy_address: String,
        exporter_addresses: Vec<String>,
        mut receiver: tokio::sync::broadcast::Receiver<Notification>,
        config: NotificationConfig,
    ) {
        let channel = tonic::transport::Channel::from_shared(proxy_address.clone())
            .expect("Proxy URI should be valid")
            .connect_lazy();
        let client = NotifierServiceClient::new(channel)
            .max_encoding_message_size(GRPC_MAX_MESSAGE_SIZE)
            .max_decoding_message_size(GRPC_MAX_MESSAGE_SIZE);

        let exporter_clients: Vec<NotifierServiceClient<Channel>> = exporter_addresses
            .iter()
            .map(|address| {
                let channel = tonic::transport::Channel::from_shared(address.clone())
                    .expect("Exporter URI should be valid")
                    .connect_lazy();
                NotifierServiceClient::new(channel)
                    .max_encoding_message_size(GRPC_MAX_MESSAGE_SIZE)
                    .max_decoding_message_size(GRPC_MAX_MESSAGE_SIZE)
            })
            .collect::<Vec<_>>();

        let mut forwarder = BatchForwarder {
            nickname: nickname.clone(),
            client,
            exporter_clients,
            pending_notifications: Vec::new(),
            futures: FuturesUnordered::new(),
            batch_limit: config.notification_batch_size,
            max_tasks: config.notification_max_in_flight,
        };

        loop {

View on GitHub (pinned to 6c226ddcb3)

Solutions

  1. Give every exporter entry the full form 'http://<host>:<port>'.
  2. Filter empty strings and trim whitespace when generating the list from env vars or templates.
  3. Add a startup sanity check that parses each entry with Uri::try_from before spawning the server.
  4. Confirm the list format against the validator configuration documentation for your version.

Example fix

# before
exporters = ["exporter1:9133", "exporter2:9133"]

# after
exporters = ["http://exporter1:9133", "http://exporter2:9133"]
Defensive patterns

Strategy: validation

Validate before calling

let bad: Vec<&String> = exporter_addresses.iter().filter(|a| a.parse::<tonic::transport::Uri>().is_err() || a.trim() != a.as_str() || a.is_empty()).collect();
if !bad.is_empty() {
    anyhow::bail!("invalid exporter URIs (need http://host:port): {bad:?}");
}

Type guard

fn all_valid_http_uris(addrs: &[String]) -> bool {
    addrs.iter().all(|a| !a.trim().is_empty() && a.parse::<tonic::transport::Uri>().map(|u| u.scheme().is_some()).unwrap_or(false))
}

Prevention

When it happens

Trigger: The validator's exporter notification list containing an entry like 'exporter1:9133' (no scheme), an empty string from an unset config variable, or an address with whitespace after comma-splitting.

Common situations: Maintaining the exporters list in validator config: adding new exporters without the http:// prefix; environment-variable templating producing empty entries; trailing commas yielding empty strings.

Related errors


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