{"record":{"id":"3ec1c6c17ca2535c","repo":"linera-io/linera-protocol","slug":"proxy-uri-should-be-valid","errorCode":null,"errorMessage":"Proxy URI should be valid","messagePattern":"Proxy URI should be valid","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"linera-rpc/src/grpc/server.rs","lineNumber":521,"sourceCode":"\n            Ok(())\n        });\n\n        GrpcServerHandle { handle }\n    }\n\n    /// Continuously waits for receiver to receive notifications and sends them to\n    /// the proxy in batches for improved throughput.\n    #[instrument(skip(receiver, config))]\n    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 {","sourceCodeStart":503,"sourceCodeEnd":539,"githubUrl":"https://github.com/linera-io/linera-protocol/blob/6c226ddcb332ef55118dc8d0aafbd093d5420899/linera-rpc/src/grpc/server.rs#L503-L539","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Write the full URI including scheme: 'http://<host>:<port>' in the proxy notification address.","Validate the address before startup: `tonic::transport::Uri::try_from(addr)` or a quick URL parse check.","Trim whitespace and remove quotes/artifacts from templated config values.","Check the validator config docs for the notification section of your version to confirm the expected format."],"exampleFix":"# before (validator config, internal proxy notification)\nproxy_address = \"10.0.0.1:9123\"   # Channel::from_shared panics: invalid URI\n\n# after\nproxy_address = \"http://10.0.0.1:9123\"","handlingStrategy":"validation","validationCode":"// Validate all notification URIs at config load, before the server starts:\nfn validate_grpc_uri(uri: &str) -> anyhow::Result<()> {\n    let parsed = uri.parse::<tonic::transport::Uri>()\n        .map_err(|e| anyhow::anyhow!(\"invalid proxy URI '{uri}': {e}\"))?;\n    anyhow::ensure!(matches!(parsed.scheme(), Some(s) if s == &http::uri::Scheme::HTTP || s == &http::uri::Scheme::HTTPS),\n        \"URI '{uri}' must include an http:// or https:// scheme\");\n    Ok(())\n}\nvalidate_grpc_uri(&config.proxy_address)?;","typeGuard":"fn is_valid_http_uri(s: &str) -> bool {\n    s.parse::<tonic::transport::Uri>().map(|u| u.scheme().is_some()).unwrap_or(false)\n}","tryCatchPattern":null,"preventionTips":["Always write notification addresses as 'http://host:port' in validator configs.","Add a config-lint step to deployment that URI-parses every proxy/exporter address.","Avoid templating addresses from unvalidated environment variables."],"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"}