denoland/deno · error · TypeError
ERR_INVALID_IP_ADDRESS
ERR_INVALID_IP_ADDRESS
Error message
Invalid IP address: ${serv} What it means
Resolver.setServers() parses each entry as an IP literal with an optional port (bracketed [v6]:port form included); the address part must pass isIP(). An entry whose address is not an IP literal throws ERR_INVALID_IP_ADDRESS naming the offending entry - hostnames and URLs are rejected because the resolver needs concrete addresses.
Source
Thrown at ext/node/polyfills/internal/dns/utils.ts:380
// addr::port
const addrSplitMatch = StringPrototypeMatch(serv, addrSplitRE);
if (addrSplitMatch) {
const hostIP = addrSplitMatch[1];
const port = addrSplitMatch[2] || `${IANA_DNS_PORT}`;
ipVersion = isIP(hostIP);
if (ipVersion !== 0) {
return ArrayPrototypePush(newSet, [
ipVersion,
hostIP,
NumberParseInt(port),
]);
}
}
throw new ERR_INVALID_IP_ADDRESS(serv);
});
const errorNumber = this._handle.setServers(newSet);
if (errorNumber !== 0) {
// Reset the servers to the old servers, because ares probably unset them.
this._handle.setServers(ArrayPrototypeJoin(orig, ","));
const err = strerror(errorNumber);
throw new ERR_DNS_SET_SERVERS_FAILED(
err,
ArrayPrototypeToString(servers),
);
}
}
/**
* The resolver instance will send its requests from the specified IP address.View on GitHub (pinned to 9ad36f7a2c)
Solutions
- Use IP literals: ['8.8.8.8', '1.1.1.1', '[2001:4860:4860::8888]:53'].
- Resolve provider hostnames once at startup and feed the resulting IPs.
- Validate every entry (IP literal, port 1-65535) before calling setServers.
Example fix
// before resolver.setServers(['dns.google', 'https://1.1.1.1/dns-query']); // after resolver.setServers(['8.8.8.8', '1.1.1.1', '[2001:4860:4860::8888]:53']);
Defensive patterns
Strategy: validation
Validate before calling
import { isIP } from 'node:net';
function looksLikeServer(s) {
if (/^\[[0-9a-fA-F:]+\](:\d+)?$/.test(s)) return true; // [ipv6] or [ipv6]:port
if (/^(\d{1,3}\.){3}\d{1,3}(:\d+)?$/.test(s)) return true; // ipv4 or ipv4:port
return isIP(s) !== 0; // bare ipv6
}
const servers = configured.filter(looksLikeServer);
if (servers.length) resolver.setServers(servers); Try / catch
try {
resolver.setServers(servers);
} catch (err) {
if (err?.code === 'ERR_INVALID_IP_ADDRESS') {
logger.warn('invalid DNS server entry; keeping defaults', err.message);
} else {
throw err;
}
} Prevention
- setServers accepts IP literals only - resolve provider hostnames (dns.google) to IPs at startup.
- Bracket IPv6 literals when adding ports: [2001:4860:4860::8888]:53.
- Validate DNS server config entries in CI with isIP-based checks.
When it happens
Trigger: resolver.setServers(['dns.google']) (hostname); ['localhost:53']; ['https://1.1.1.1/dns-query'] (DoH URL); a malformed literal like '192.168.0'.
Common situations: Wanting DoH-style resolver names where only IPs work; DNS config scraped from systemd-resolved, docker or k8s templates that contain hostnames; env-var lists with typos.
Related errors
- ERR_DNS_SET_SERVERS_FAILED
- ERR_INVALID_ARG_VALUE
- ERR_INVALID_ARG_VALUE
- The url passed into 'proxy.url' has an invalid scheme for th
- ERR_OUT_OF_RANGE
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/088bb72963243947.
Report an issue: GitHub.