{"record":{"id":"41785ffa116d6354","repo":"denoland/deno","slug":"invalid-ip-address-addr0","errorCode":null,"errorMessage":"Invalid IP address: ${addr0}","messagePattern":"Invalid IP address: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"ext/node/polyfills/internal_binding/cares_wrap.ts","lineNumber":926,"sourceCode":"  setLocalAddress(addr0: string, addr1?: string) {\n    // Mirror Node's c-ares `ChannelWrap::SetLocalAddress`: the first argument\n    // may be either an IPv4 or IPv6 address; if a second argument is given it\n    // must be the *other* family (so exactly one IPv4 and one IPv6 address, in\n    // either order). The caller (`Resolver.setLocalAddress` in\n    // `internal/dns/utils.ts`) has already validated the arguments are strings.\n    //\n    // We validate the addresses here and record them so the call no longer\n    // throws and matches Node's observable behavior. The underlying resolver op\n    // (`op_dns_resolve`) does not yet expose a per-query bind address, so the\n    // stored value is not applied to outgoing queries; see\n    // https://github.com/denoland/deno/issues/36518.\n    let type0: 4 | 6;\n    if (isIPv4(addr0)) {\n      type0 = 4;\n    } else if (isIPv6(addr0)) {\n      type0 = 6;\n    } else {\n      throw new Error(`Invalid IP address: ${addr0}`);\n    }\n\n    if (addr1 !== undefined) {\n      if (isIPv4(addr1)) {\n        if (type0 === 4) {\n          throw new Error(\"Cannot specify two IPv4 addresses\");\n        }\n      } else if (isIPv6(addr1)) {\n        if (type0 === 6) {\n          throw new Error(\"Cannot specify two IPv6 addresses\");\n        }\n      } else {\n        throw new Error(`Invalid IP address: ${addr1}`);\n      }\n    }\n\n    this.#localAddress = {\n      ipv4: type0 === 4 ? addr0 : addr1,","sourceCodeStart":908,"sourceCodeEnd":944,"githubUrl":"https://github.com/denoland/deno/blob/a961cdec3b1948844414ebeecc697dcad76df2d1/ext/node/polyfills/internal_binding/cares_wrap.ts#L908-L944","documentation":"ChannelWrap's lookup-like methods accept a primary local address (addr0) that must be a valid IPv4 or IPv6 literal. The address is validated with isIPv4/isIPv6 before being stored in #localAddress for use with c-ares name resolution. If addr0 parses as neither, this error is thrown to prevent passing a malformed binding address to the resolver.","triggerScenarios":"Calling ChannelWrap methods that accept a local address (e.g. getAddrInfo/lookup via the Resolver with a localAddress option) where addr0 is not a valid IPv4 or IPv6 literal — e.g. a hostname like 'localhost', an empty string, or a typo like '192.168.1.256'.","commonSituations":"Passing a hostname instead of an IP literal in dns.Resolver localAddress/localPort options; reading the address from config or an env var that contains a name rather than a literal; IPv6 written with a zone index or invalid shorthand that fails strict parsing.","solutions":["Pass a valid IP literal (e.g. '0.0.0.0', '::') instead of a hostname in the localAddress option.","Validate the string with isIPv4/isIPv6 (or a regex) before passing it to the resolver.","Resolve a hostname to an IP first (dns.lookup) if you only have a name, then pass the resulting literal."],"exampleFix":"// before\nconst resolver = new dns.Resolver({ localAddress: 'my-host.internal' });\n// after\nconst addresses = await dns.promises.lookup('my-host.internal');\nconst resolver = new dns.Resolver({ localAddress: addresses[0].address });","handlingStrategy":"validation","validationCode":"function isValidIp(addr) {\n  const v4 = /^(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}$/;\n  const v6 = /^[0-9a-fA-F:]+$/; // plus a strict isIPv6 check\n  return v4.test(addr) || isIPv6(addr);\n}\nif (!isValidIp(addr0)) throw new Error(`Refusing to bind local address: ${addr0}`);","typeGuard":"function isIpLiteral(addr) {\n  return typeof addr === 'string' && (isIPv4(addr) || isIPv6(addr));\n}","tryCatchPattern":"try {\n  channel.lookup(...);\n} catch (err) {\n  if (String(err.message).startsWith('Invalid IP address')) {\n    // fall back to no localAddress binding\n  }\n}","preventionTips":["Always pass IP literals, never hostnames, as localAddress options.","Run addresses through isIPv4/isIPv6 at config load time and fail fast.","Resolve hostnames to addresses once at startup, then cache the literals."],"tags":["dns","node-compat","validation"],"backgroundTag":"invalid-ip-address","analyzedSha":"a961cdec3b1948844414ebeecc697dcad76df2d1","analyzedAt":"2026-09-03T14:18:07.398Z","contentChangedAt":"2026-09-03T14:18:07.398Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}