{"record":{"id":"e76279d8da989798","repo":"n0-computer/iroh","slug":"only-a-single-default-address-can-be-set-per-ip-fa","errorCode":null,"errorMessage":"Only a single default address can be set per IP family","messagePattern":"Only a single default address can be set per IP family","errorType":"validation","errorClass":"InvalidSocketAddr","httpStatus":null,"severity":"error","filePath":"iroh/src/endpoint.rs","lineNumber":467,"sourceCode":"    #[cfg(not(wasm_browser))]\n    pub fn bind_addr_with_opts<A>(\n        mut self,\n        addr: A,\n        opts: BindOpts,\n    ) -> Result<Self, InvalidSocketAddr>\n    where\n        A: ToSocketAddr,\n        <A as ToSocketAddr>::Err: Into<InvalidSocketAddr>,\n    {\n        let addr = addr.to_socket_addr().map_err(Into::into)?;\n        match addr {\n            SocketAddr::V4(addr) => {\n                if self\n                    .transports\n                    .iter()\n                    .any(|t| t.is_ipv4_default() && t.is_user_defined())\n                {\n                    bail!(InvalidSocketAddr::DuplicateDefaultAddr);\n                }\n\n                let ip_net = Ipv4Net::new(*addr.ip(), opts.prefix_len())\n                    .map_err(|_| e!(InvalidSocketAddr::InvalidPrefixLength))?;\n                self.transports.push(TransportConfig::Ip {\n                    config: IpConfig::V4 {\n                        ip_net,\n                        port: addr.port(),\n                        is_required: opts.is_required(),\n                        is_default: opts.is_default_route(),\n                    },\n                    is_user_defined: true,\n                });\n            }\n            SocketAddr::V6(addr) => {\n                if self\n                    .transports\n                    .iter()","sourceCodeStart":449,"sourceCodeEnd":485,"githubUrl":"https://github.com/n0-computer/iroh/blob/2b4de030ce5e0133f272871a76f0c685c63f552a/iroh/src/endpoint.rs#L449-L485","documentation":"InvalidSocketAddr::DuplicateDefaultAddr from iroh's Endpoint::bind_addr_with_opts. When binding an IPv4 transport, the code checks whether a user-defined IPv4 default transport already exists; if so, adding another default address for the same IP family is rejected. Only one default (0.0.0.0/::) address per family is allowed.","triggerScenarios":"Calling endpoint.bind_addr_v4 or bind_addr with a default/unspecified IPv4 address (0.0.0.0) when self.transports already contains a user-defined IPv4 default transport (is_ipv4_default() && is_user_defined()).","commonSituations":"Calling bind_addr_v4 twice on the same endpoint builder; mixing a config-provided default bind with a programmatic default bind; migrating code that previously allowed rebinding defaults.","solutions":["Bind the IPv4 default address only once per endpoint; remove duplicate bind_addr_v4 calls.","Bind a specific address instead of the default (0.0.0.0) for the second transport.","Inspect endpoint.transports (or your builder config) before binding to detect an existing user-defined IPv4 default.","If you need multiple listeners, use separate endpoints rather than multiple default transports."],"exampleFix":"// before\nendpoint.bind_addr_v4(\"0.0.0.0:0\".parse()?); // second default v4 bind -> error\n// after\nif !endpoint.has_ipv4_default() {\n    endpoint.bind_addr_v4(\"0.0.0.0:0\".parse()?);\n}","handlingStrategy":"validation","validationCode":"fn can_bind_v4_default(transports: &[TransportConfig]) -> bool {\n    !transports.iter().any(|t| t.is_ipv4_default() && t.is_user_defined())\n}","typeGuard":null,"tryCatchPattern":"match endpoint.bind_addr_v4(addr) {\n    Err(e) if e.to_string().contains(\"default address\") => { /* v4 default already bound; skip */ }\n    other => other?,\n}","preventionTips":["Call bind_addr_v4 at most once per endpoint","Track bound defaults in your config layer before constructing the endpoint","Use specific addresses for secondary transports","Guard builder calls with a check for existing user-defined default transports"],"tags":["network","configuration","binding","ipv4"],"backgroundTag":"conflicting-config-options","analyzedSha":"2b4de030ce5e0133f272871a76f0c685c63f552a","analyzedAt":"2026-09-08T04:26:47.755Z","contentChangedAt":"2026-09-08T04:26:47.755Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}