{"record":{"id":"477d55efd70faac8","repo":"quickwit-oss/quickwit","slug":"provided-arguments-should-be-valid","errorCode":null,"errorMessage":"provided arguments should be valid","messagePattern":"provided arguments should be valid","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"quickwit/quickwit-transport/src/channel.rs","lineNumber":98,"sourceCode":"                expected_server_name,\n            },\n        })\n    }\n\n    /// Creates a lazily-connected channel to `socket_addr`. The channel reconnects through this\n    /// factory's transport, so a reloaded certificate takes effect on the next (re)connection\n    /// without rebuilding the channel.\n    ///\n    /// The function is `async` because `connect_lazy` requires a Tokio runtime context.\n    pub async fn make_channel(&self, socket_addr: SocketAddr) -> Channel {\n        // The scheme is always `http`: when TLS is enabled our custom connector hands tonic an\n        // already-encrypted stream, so tonic must not attempt its own TLS.\n        let uri = Uri::builder()\n            .scheme(\"http\")\n            .authority(socket_addr.to_string())\n            .path_and_query(\"/\")\n            .build()\n            .expect(\"provided arguments should be valid\");\n\n        let mut endpoint = Endpoint::from(uri).connect_timeout(CONNECT_TIMEOUT);\n\n        if let Some(keep_alive) = &self.keep_alive_opt {\n            endpoint = endpoint\n                .keep_alive_while_idle(true)\n                .http2_keep_alive_interval(*keep_alive.interval)\n                .keep_alive_timeout(*keep_alive.timeout);\n        }\n        match &self.mode {\n            TransportMode::Plaintext => endpoint.connect_lazy(),\n            TransportMode::Tls {\n                client_config,\n                expected_server_name,\n            } => {\n                let tls_connector = TlsConnector::from(client_config.clone());\n                let server_name = match expected_server_name {\n                    Some(server_name) => server_name.clone(),","sourceCodeStart":80,"sourceCodeEnd":116,"githubUrl":"https://github.com/quickwit-oss/quickwit/blob/a39730c5cdcd1a4fe798403737ae293999ea21f8/quickwit/quickwit-transport/src/channel.rs#L80-L116","documentation":"This panic occurs in `make_channel` when constructing a tonic gRPC `Endpoint` from a `http::Uri` built from the target socket address. It asserts that the URI `http://<socket_addr>/` is well-formed; failure means the authority (the `SocketAddr` string) could not be parsed as a valid URI authority. Because a `SocketAddr` is always `ip:port` and always yields a valid authority, this is effectively an internal invariant assertion guarding against non-IP/invalid addresses reaching this code path.","triggerScenarios":"Calling `make_channel` (via `try_new_node` or `cluster_grpc_client`) with a target whose `SocketAddr` string cannot form a valid URI — practically only possible with a malformed custom `EndpointFactory` configuration or if code upstream passes a hostname/string-derived address that fails `Uri::builder(...).build()` instead of a real `SocketAddr`.","commonSituations":"Misconfigured node gRPC address (e.g. an IPv6 address rendered without brackets, or a string address incorrectly parsed upstream); custom code paths in a fork passing a URI-incompatible authority.","solutions":["Verify the gRPC address configured for the node is a valid `ip:port` (wrap IPv6 literals in brackets when written in configs, though `SocketAddr` handles this)","Check upstream parsing of the address into `SocketAddr` — a failed parse should error earlier, so a panic here usually means a fork/patch bypassed parsing","Rebuild from unmodified sources; on stock Quickwit a valid `SocketAddr` never triggers this","If reproducing on unmodified code, file a bug with the address string"],"exampleFix":"// before (passing a hostname string through a SocketAddr-typed path)\nlet uri = Uri::builder().scheme(\"http\").authority(\"node.local\").build().expect(\"provided arguments should be valid\");\n// after\nlet socket_addr: SocketAddr = \"node.local:7281\".parse().expect(\"invalid gRPC address\");\nlet uri = Uri::builder().scheme(\"http\").authority(socket_addr.to_string()).build().expect(\"provided arguments should be valid\");","handlingStrategy":"validation","validationCode":"fn validate_grpc_addr(addr: SocketAddr) -> Option<Uri> {\n    Uri::builder()\n        .scheme(\"http\")\n        .authority(addr.to_string())\n        .path_and_query(\"/\")\n        .build()\n        .ok()\n}","typeGuard":"fn is_valid_authority(s: &str) -> bool {\n    http::Uri::builder().scheme(\"http\").authority(s).path_and_query(\"/\").build().is_ok()\n}","tryCatchPattern":"// make_channel panics rather than returning Result; guard upstream by parsing to SocketAddr first\nlet socket_addr: SocketAddr = addr_str.parse().map_err(|e| anyhow!(\"invalid gRPC address '{}': {}\", addr_str, e))?;","preventionTips":["Always parse configured addresses into SocketAddr (which validates ip:port) before calling channel construction","Write IPv6 addresses in configs correctly (SocketAddr output includes brackets automatically)","Keep the endpoint construction unmodified in forks; the constant URI is only valid for ip:port authorities"],"tags":["rust","grpc","uri","networking"],"backgroundTag":"invalid-url","analyzedSha":"a39730c5cdcd1a4fe798403737ae293999ea21f8","analyzedAt":"2026-09-08T13:19:37.784Z","contentChangedAt":"2026-09-08T13:19:37.784Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}