{"record":{"id":"9791daa06dd6d2f6","repo":"linera-io/linera-protocol","slug":"expecting-format-tcp-udp-grpc-grpcs-host-port","errorCode":null,"errorMessage":"Expecting format `(tcp|udp|grpc|grpcs):host:port`","messagePattern":"Expecting format `\\(tcp\\|udp\\|grpc\\|grpcs\\):host:port`","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"linera-rpc/src/config.rs","lineNumber":276,"sourceCode":"            NetworkProtocol::Simple(protocol) => write!(f, \"{protocol:?}\"),\n            NetworkProtocol::Grpc(tls) => match tls {\n                TlsConfig::ClearText => write!(f, \"grpc\"),\n                TlsConfig::Tls => write!(f, \"grpcs\"),\n            },\n        }\n    }\n}\n\nimpl<P> std::str::FromStr for ValidatorPublicNetworkPreConfig<P>\nwhere\n    P: std::str::FromStr,\n    P::Err: std::fmt::Display,\n{\n    type Err = anyhow::Error;\n\n    fn from_str(s: &str) -> Result<Self, Self::Err> {\n        let parts = s.split(':').collect::<Vec<_>>();\n        anyhow::ensure!(\n            parts.len() == 3,\n            \"Expecting format `(tcp|udp|grpc|grpcs):host:port`\"\n        );\n        let protocol = parts[0].parse().map_err(|s| anyhow::anyhow!(\"{s}\"))?;\n        let host = parts[1].to_owned();\n        let port = parts[2].parse()?;\n        Ok(ValidatorPublicNetworkPreConfig {\n            protocol,\n            host,\n            port,\n        })\n    }\n}\n\nimpl std::str::FromStr for NetworkProtocol {\n    type Err = String;\n\n    fn from_str(s: &str) -> Result<Self, Self::Err> {","sourceCodeStart":258,"sourceCodeEnd":294,"githubUrl":"https://github.com/linera-io/linera-protocol/blob/6c226ddcb332ef55118dc8d0aafbd093d5420899/linera-rpc/src/config.rs#L258-L294","documentation":"A validator network address string did not split into exactly three ':'-separated parts. ValidatorPublicNetworkPreConfig::from_str parses `protocol:host:port` with a plain split(':'), so anything that is not exactly three segments fails this shape check before protocol or port are even looked at.","triggerScenarios":"Missing port (\"grpc:validator1\"), extra segments (\"grpc:host:9000:extra\"), URL-style schemes (\"grpc://host:9000\" keeps 3 parts but \"https://host:9000/\" does not), and IPv6 literals (\"tcp:::1:9000\" splits into 5 parts) all produce a segment count != 3.","commonSituations":"Pasting URLs from browser/RPC docs into validator config; copy-pasting addresses with trailing colons or whitespace; IPv6 hosts, which this parser cannot express because the colons inside the literal break the 3-part split.","solutions":["Rewrite the value as exactly protocol:host:port, e.g. \"grpc:validator1.example.com:9000\".","Drop \"://\" from scheme-style URLs — the parser wants \"grpc:host:port\", not \"grpc://host:port\".","For IPv6, use a DNS hostname or IPv4 address instead; unbracketed or bracketed literals both fail the split.","Trim stray whitespace/colons when generating the value programmatically."],"exampleFix":"# before: wrong shapes\n\"grpc://validator1:9000/x\"   # extra path segment\n\"tcp:::1:9000\"                # IPv6 literal -> 5 parts\n\"grpc:validator1\"             # missing port\n\n# after: exactly three ':'-separated parts\n\"grpc:validator1.example.com:9000\"\n\"tcp:10.0.0.1:9000\"","handlingStrategy":"type-guard","validationCode":"fn is_valid_transport_spec(s: &str) -> bool {\n    let mut parts = s.split(':');\n    matches!(parts.next(), Some(\"tcp\" | \"udp\" | \"grpc\" | \"grpcs\"))\n        && matches!(parts.next(), Some(h) if !h.is_empty() && !h.contains(':'))\n        && parts.next().is_some_and(|p| p.parse::<u16>().is_ok())\n        && parts.next().is_none()\n}","typeGuard":"fn is_valid_transport_spec(s: &str) -> bool {\n    let mut parts = s.split(':');\n    matches!(parts.next(), Some(\"tcp\" | \"udp\" | \"grpc\" | \"grpcs\"))\n        && matches!(parts.next(), Some(h) if !h.is_empty())\n        && parts.next().is_some_and(|p| p.parse::<u16>().is_ok())\n        && parts.next().is_none()\n}","tryCatchPattern":null,"preventionTips":["Generate validator addresses as format!(\"{protocol}:{host}:{port}\") instead of string concatenation.","Remember this format cannot express IPv6 literals — use hostnames.","Validate specs in config-loading code so errors surface with file/line context."],"tags":["config","parsing","network-address","validator"],"backgroundTag":"invalid-endpoint-format","analyzedSha":"6c226ddcb332ef55118dc8d0aafbd093d5420899","analyzedAt":"2026-08-22T22:49:09.787Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}