linera-io/linera-protocol · error

Proxy URI should be valid

Error message

Proxy URI should be valid

What it means

forward_notifications (linera-rpc/src/grpc/server.rs:513) builds a tonic Channel from the configured proxy address string with Channel::from_shared(...).expect("Proxy URI should be valid"). from_shared fails when the string is not a valid http/https URI - missing scheme (bare host:port), whitespace, invalid characters, or unsupported scheme. The panic kills the notification-forwarding task on the validator, so notifications stop flowing to the proxy.

Source

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

            Ok(())
        });

        GrpcServerHandle { handle }
    }

    /// Continuously waits for receiver to receive notifications and sends them to
    /// the proxy in batches for improved throughput.
    #[instrument(skip(receiver, config))]
    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 {

View on GitHub (pinned to 6c226ddcb3)

Solutions

  1. Write the full URI including scheme: 'http://<host>:<port>' in the proxy notification address.
  2. Validate the address before startup: `tonic::transport::Uri::try_from(addr)` or a quick URL parse check.
  3. Trim whitespace and remove quotes/artifacts from templated config values.
  4. Check the validator config docs for the notification section of your version to confirm the expected format.

Example fix

# before (validator config, internal proxy notification)
proxy_address = "10.0.0.1:9123"   # Channel::from_shared panics: invalid URI

# after
proxy_address = "http://10.0.0.1:9123"
Defensive patterns

Strategy: validation

Validate before calling

// Validate all notification URIs at config load, before the server starts:
fn validate_grpc_uri(uri: &str) -> anyhow::Result<()> {
    let parsed = uri.parse::<tonic::transport::Uri>()
        .map_err(|e| anyhow::anyhow!("invalid proxy URI '{uri}': {e}"))?;
    anyhow::ensure!(matches!(parsed.scheme(), Some(s) if s == &http::uri::Scheme::HTTP || s == &http::uri::Scheme::HTTPS),
        "URI '{uri}' must include an http:// or https:// scheme");
    Ok(())
}
validate_grpc_uri(&config.proxy_address)?;

Type guard

fn is_valid_http_uri(s: &str) -> bool {
    s.parse::<tonic::transport::Uri>().map(|u| u.scheme().is_some()).unwrap_or(false)
}

Prevention

When it happens

Trigger: Configuring a validator's internal proxy notification address as a bare 'host:port' (e.g. '10.0.0.1:9123') instead of 'http://10.0.0.1:9123', or including whitespace/copy-paste artifacts in the address from the validator config file.

Common situations: Hand-writing validator TOML with internal/proxy notification sections; addresses copied from other config styles (socks://, grpc://, or no scheme); config templating that injects stray characters.

Related errors


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