node:dns: reject falsy hostnames in lookup() with ERR_INVALID_ARG_VALUE
RO
3mo ago+133+133+012345678901234567890123456789-105-105-012345678901234567890123456789
Fixes #37464
Problem
dns.lookup("", cb)(andnull,undefined,false,0,NaN) calls back withaddress: null, family: 4(or[]withall: true) and prints aDEP0118DeprecationWarning.dns.promises.lookup("")resolves with the same value.- DEP0118 reached end of life in Node v25.0.0 (nodejs/node#58619). Node 25+ throws
ERR_INVALID_ARG_VALUE("The argument 'hostname' must be a non-empty string. Received ''") fromdns.lookup, anddns.promises.lookupreturns a promise rejected with the same error. Bun reportsprocess.versionv26.3.0, so code written against the Node version Bun claims expects the error. - Cause:
src/js/node/dns.tsstill has the legacy path.lookup()andpromises.lookup()callinvalidHostname()to emit the warning and then report success for a hostname that was never looked up.
Fix
- Callback
dns.lookup: throwERR_INVALID_ARG_VALUEsynchronously when the hostname is falsy. The check stays after callback and option validation, which is the order Node uses, so argument type errors still win over the empty hostname error. dns.promises.lookup: returnPromise.reject(ERR_INVALID_ARG_VALUE)for a falsy hostname, again after option validation. Node does this insidecreateLookupPromise, so the error is a rejection there, not a synchronous throw; a caller doinglookup(host).catch(...)(orutil.promisify(dns.lookup)) keeps working the same way in both runtimes.- Removed the
invalidHostname()DEP0118 helper, which has no remaining callers. - Error code, message, and the falsy set (
"",null,undefined,false,0,NaN) match Node v26.3.0 output for the same inputs. - Internal callers are unaffected:
netdefaults an empty host to"localhost"before callinglookup(as Node does),dgramdefaults to the loopback address, and the cluster listen path checksaddress.length > 0first. - Synced
test-dns.js,test-dns-lookup.js, andtest-c-ares.jswhere they asserted the removed DEP0118 behavior. The updated files pass under Node v26.3.0. - Verified:
bun bd test test/js/node/dns/node-dns.test.js -t "falsy hostname"(13 tests; all fail on main, all pass with this change; the rest of the file has the same set of network dependent failures with and without the change). - Verified:
bun bd test/js/node/test/parallel/test-dns.js,test-dns-lookup.js,test-c-ares.jsexit 0 with the change and fail on main with "Missing expected rejection". - The branch was merged with current main after
dns.lookupmoved to the system resolver (#37383, #37319) and re-verified with the steps above; the diff against main is unchanged.
Background
DEP0118: the Node deprecation that covered passing a falsy hostname todns.lookup. While it was active (runtime deprecated since v11), Node treated such a call as a successful lookup of nothing (address: null) and printed a warning once. It reached end of life in v25.0.0, so current Node rejects the argument instead.ERR_INVALID_ARG_VALUE: Node's error for an argument that has the right type but an unacceptable value;ERR_INVALID_ARG_TYPE(already thrown here for truthy non-string hostnames) is the type counterpart.$ERR_INVALID_ARG_VALUE(name, value, reason)is the builtin helper that creates it with Node's message format.- Sync throw vs rejection: in Node, argument type checks in
dns.promises.lookuprun before the promise is created (so they throw), while the falsy hostname check runs inside the promise executor (so it rejects). This change keeps the same split.
Reproduction
import dnsp from "node:dns/promises";
const cap = (p) => p.then((ok) => ({ ok }), (e) => ({ err: { ctor: e.constructor.name, code: e.code } }));
console.log("lookup(''): ", JSON.stringify(await cap(dnsp.lookup(""))));
console.log("lookup(null):", JSON.stringify(await cap(dnsp.lookup(null))));
Node v26.3.0:
lookup(''): {"err":{"ctor":"TypeError","code":"ERR_INVALID_ARG_VALUE"}}
lookup(null): {"err":{"ctor":"TypeError","code":"ERR_INVALID_ARG_VALUE"}}
Bun 1.4.0 (before this change):
lookup(''): {"ok":{"address":null,"family":4}}
lookup(null): {"ok":{"address":null,"family":4}}
DeprecationWarning: The provided hostname "" is not a valid hostname, and is supported in the dns module solely for compatibility.
code: "DEP0118"
no test proof · iteration 1 · Platform-specific test(s) that do not run on this machine. Deferring to CI, which covers all platforms: test/js/node/dns/node-dns.test.js