{"record":{"id":"d3d5ede26db92057","repo":"linera-io/linera-protocol","slug":"exporter-uri-should-be-valid","errorCode":null,"errorMessage":"Exporter URI should be valid","messagePattern":"Exporter URI should be valid","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"linera-rpc/src/grpc/server.rs","lineNumber":531,"sourceCode":"    async fn forward_notifications(\n        nickname: String,\n        proxy_address: String,\n        exporter_addresses: Vec<String>,\n        mut receiver: tokio::sync::broadcast::Receiver<Notification>,\n        config: NotificationConfig,\n    ) {\n        let channel = tonic::transport::Channel::from_shared(proxy_address.clone())\n            .expect(\"Proxy URI should be valid\")\n            .connect_lazy();\n        let client = NotifierServiceClient::new(channel)\n            .max_encoding_message_size(GRPC_MAX_MESSAGE_SIZE)\n            .max_decoding_message_size(GRPC_MAX_MESSAGE_SIZE);\n\n        let exporter_clients: Vec<NotifierServiceClient<Channel>> = exporter_addresses\n            .iter()\n            .map(|address| {\n                let channel = tonic::transport::Channel::from_shared(address.clone())\n                    .expect(\"Exporter URI should be valid\")\n                    .connect_lazy();\n                NotifierServiceClient::new(channel)\n                    .max_encoding_message_size(GRPC_MAX_MESSAGE_SIZE)\n                    .max_decoding_message_size(GRPC_MAX_MESSAGE_SIZE)\n            })\n            .collect::<Vec<_>>();\n\n        let mut forwarder = BatchForwarder {\n            nickname: nickname.clone(),\n            client,\n            exporter_clients,\n            pending_notifications: Vec::new(),\n            futures: FuturesUnordered::new(),\n            batch_limit: config.notification_batch_size,\n            max_tasks: config.notification_max_in_flight,\n        };\n\n        loop {","sourceCodeStart":513,"sourceCodeEnd":549,"githubUrl":"https://github.com/linera-io/linera-protocol/blob/6c226ddcb332ef55118dc8d0aafbd093d5420899/linera-rpc/src/grpc/server.rs#L513-L549","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"# before\nexporters = [\"exporter1:9133\", \"exporter2:9133\"]\n\n# after\nexporters = [\"http://exporter1:9133\", \"http://exporter2:9133\"]","handlingStrategy":"validation","validationCode":"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();\nif !bad.is_empty() {\n    anyhow::bail!(\"invalid exporter URIs (need http://host:port): {bad:?}\");\n}","typeGuard":"fn all_valid_http_uris(addrs: &[String]) -> bool {\n    addrs.iter().all(|a| !a.trim().is_empty() && a.parse::<tonic::transport::Uri>().map(|u| u.scheme().is_some()).unwrap_or(false))\n}","tryCatchPattern":null,"preventionTips":["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."],"tags":["linera-rpc","grpc","tonic","invalid-uri","configuration","panic"],"backgroundTag":"invalid-grpc-endpoint","analyzedSha":"6c226ddcb332ef55118dc8d0aafbd093d5420899","analyzedAt":"2026-08-22T22:49:09.787Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}