{"record":{"id":"04ce1d4f49342956","repo":"denoland/deno","slug":"invalid-ipv4-address","errorCode":null,"errorMessage":"invalid IPv4 address","messagePattern":"invalid IPv4 address","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"ext/node/ops/udp.rs","lineNumber":375,"sourceCode":"  sock_ref.set_ttl(ttl)?;\n  Ok(())\n}\n\n#[op2(fast)]\npub fn op_node_udp_set_multicast_interface(\n  state: &mut OpState,\n  #[smi] rid: ResourceId,\n  is_ipv6: bool,\n  #[string] interface_address: &str,\n) -> Result<(), NodeUdpError> {\n  let resource = state.resource_table.get::<NodeUdpSocketResource>(rid)?;\n  let sock_ref = socket2::SockRef::from(&resource.socket);\n  if is_ipv6 {\n    let index = ipv6_interface_index(interface_address)?;\n    sock_ref.set_multicast_if_v6(index)?;\n  } else {\n    let addr: Ipv4Addr = interface_address.parse().map_err(|_| {\n      NodeUdpError::Io(std::io::Error::new(\n        std::io::ErrorKind::InvalidInput,\n        \"invalid IPv4 address\",\n      ))\n    })?;\n    sock_ref.set_multicast_if_v4(&addr)?;\n  }\n  Ok(())\n}\n\n/// Parse an IPv6 interface address string to a network interface index.\n/// Matches libuv's `uv__udp_set_multicast_interface6` behavior:\n/// - Parses IPv6 address strings like `::%lo0`, `::%1`, `::`\n/// - Extracts scope_id and resolves interface names via if_nametoindex\n/// - Returns EINVAL for empty or unparseable addresses\nfn ipv6_interface_index(interface_address: &str) -> Result<u32, NodeUdpError> {\n  let einval =\n    || NodeUdpError::Io(std::io::Error::from_raw_os_error(libc::EINVAL));\n","sourceCodeStart":357,"sourceCodeEnd":393,"githubUrl":"https://github.com/denoland/deno/blob/a961cdec3b1948844414ebeecc697dcad76df2d1/ext/node/ops/udp.rs#L357-L393","documentation":"Thrown by Deno's node:dgram implementation of socket.setMulticastInterface (op_node_udp_set_multicast_interface, ext/node/ops/udp.rs). When the socket is IPv4 (is_ipv6=false), the interface argument is parsed with Rust's Ipv4Addr::parse; any value that is not a literal dotted-quad IPv4 address fails with ErrorKind::InvalidInput and this message. This mirrors libuv, which returns EINVAL for an unparseable multicast interface address.","triggerScenarios":"Calling dgram socket.setMulticastInterface(x) on a socket bound to IPv4 where x is not an IPv4 literal: an IPv6 address ('::1'), an interface name ('eth0'), a hostname ('localhost'), an empty string, or a scoped address ('fe80::1%eth0'). Only dotted-quad literals like '0.0.0.0', '127.0.0.1', or a local NIC address such as '192.168.1.5' are accepted.","commonSituations":"Config values copied from C examples that use interface names; code ported between IPv4 and IPv6 sockets without changing the interface argument; env-provided MULTICAST_IFACE misconfigured; confusion between 'any' (0.0.0.0) and loopback; passing the result of os.networkInterfaces() fields of the wrong family.","solutions":["Pass a valid IPv4 literal matching the socket family: '0.0.0.0' for the default interface, or the address of a NIC from os.networkInterfaces() where family === 'IPv4'.","If the socket is IPv6, pass an IPv6 literal with optional zone ('::' or 'fe80::1%eth0'); do not mix families between bind() and setMulticastInterface().","Validate the value with node:net isIPv4()/isIPv6() before calling the API and fail fast with the offending value in the message.","If the value comes from config, log it when EINVAL is caught so the bad input is visible."],"exampleFix":"// before\nsock.setMulticastInterface(process.env.MULTICAST_IFACE ?? \"eth0\"); // EINVAL: invalid IPv4 address\n\n// after\nimport { isIPv4, isIPv6 } from \"node:net\";\nimport { networkInterfaces } from \"node:os\";\nconst anyV4 = Object.values(networkInterfaces()).flat().find(a => a?.family === \"IPv4\")?.address ?? \"0.0.0.0\";\nconst iface = process.env.MULTICAST_IFACE ?? anyV4;\nif (sock.address().family === \"IPv4\" && !isIPv4(iface)) throw new Error(`MULTICAST_IFACE must be IPv4, got ${iface}`);\nif (sock.address().family === \"IPv6\" && !isIPv6(iface)) throw new Error(`MULTICAST_IFACE must be IPv6, got ${iface}`);\nsock.setMulticastInterface(iface);","handlingStrategy":"validation","validationCode":"import { isIPv4 } from \"node:net\";\nconst iface = process.env.MULTICAST_IFACE ?? \"0.0.0.0\";\nif (!isIPv4(iface)) throw new Error(`MULTICAST_IFACE must be an IPv4 literal, got: ${iface}`);\nsock.setMulticastInterface(iface);","typeGuard":"import { isIPv4 } from \"node:net\";\nconst isIPv4Literal = (v: string): v is `${number}.${number}.${number}.${number}` => isIPv4(v);","tryCatchPattern":"try { sock.setMulticastInterface(iface); } catch (e) { if (e instanceof Error && /invalid IPv4 address/.test(e.message)) throw new Error(`bad MULTICAST_IFACE: ${JSON.stringify(iface)}`); throw e; }","preventionTips":["Never pass interface names or hostnames to setMulticastInterface; only IP literals.","Pick the interface from os.networkInterfaces() filtered by the socket's family so families can never mismatch.","Validate config-supplied addresses at startup with node:net isIPv4/isIPv6 and fail fast."],"tags":["udp","dgram","multicast","ipv4","node-compat","invalid-input"],"backgroundTag":"invalid-ip-address","analyzedSha":"a961cdec3b1948844414ebeecc697dcad76df2d1","analyzedAt":"2026-08-20T13:07:44.778Z","contentChangedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}