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
- Give every exporter entry the full form 'http://<host>:<port>'.
- Filter empty strings and trim whitespace when generating the list from env vars or templates.
- Add a startup sanity check that parses each entry with Uri::try_from before spawning the server.
- 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
- Normalize every exporter entry to 'http://host:port' when generating configs.
- Trim whitespace and drop empty entries when building the list from env vars or CSVs.
- Unit-test config parsing with a URI validation pass so bad entries fail at deploy time, not at runtime.
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
- Proxy URI should be valid
- invalid block export configuration: {message}
- MissingCertificates
- InconsistentChainId
- a running notification server
AI-assisted analysis of linera-io/linera-protocol@6c226ddcb3 (2026-08-22).
Data as JSON: /api/errors/d3d5ede26db92057.
Report an issue: GitHub.