fix(runtime): node:dns — correct resolve/reverse error shape (syscall + hostname); 6/6 node-suite#5077
Conversation
… + hostname)
node:dns node-suite: 5/6 -> 6/6 locally (zero regressions in
assert/net/dgram + dns_resolver unit tests + error-shape probes).
Root causes:
1. resolve*/reverse rejections were missing Node's `.syscall` and
`.hostname` own properties. A caught `dns.resolve4` error exposed only
`.code` ("ESERVFAIL"); Node's c-ares errors also carry
`e.syscall === "queryA"` and `e.hostname === "localhost"` (with
`errno` left undefined). `dns.reverse` errors likewise carry
`syscall === "getHostByAddr"`.
- dns.rs: new `dns_query_error_value` builds the error and registers
code + syscall + hostname on the message StringHeader (mirrors the
existing `.code` side-table path); resolve_error_value /
reverse_error_value route through it.
- node_submodules/diagnostics.rs: new ERROR_MESSAGE_HOSTNAMES side
table + register_error_hostname / error_hostname_for_message,
paralleling the syscall/path/dest tables.
- object/field_get_set.rs: new `.hostname` Error getter arm (mirrors
`.path`/`.syscall`). The user-assigned-prop path is consulted first,
so a user-set `err.hostname` still wins — verified against Node.
2. test imports/default-export.ts asserted that
`resolver.resolve4("localhost")` returns an array. resolve4 queries the
configured nameserver directly (it does NOT consult /etc/hosts), so
"localhost" yields an A record on some resolvers and
ESERVFAIL/ENOTFOUND on others — on a SERVFAIL machine Node itself
aborts on the unhandled rejection, making the assertion unportable.
Rewrote it to print array-or-error-code, the same environment-robust
record-or-error approach #5040 already applied to the sibling
dns/resolve/localhost.ts test. (No product behavior was papered over:
Perry already threw the correct ESERVFAIL there — the fix above just
completes that error's shape.)
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (4)
📝 WalkthroughWalkthroughThis PR adds ChangesDNS Error Hostname Support
🎯 3 (Moderate) | ⏱️ ~25 minutes
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
Summary
Investigated the report that node:dns was crashing on all 6 node-suite tests. The "0/6 crash" premise was stale for this environment — on a pristine
origin/mainworktree the dns node-suite already measured 5/6 with no panics or segfaults (the #5040 hosts-file reverse logic is correct here — this machine's/etc/hostsproduces exactly node's["proxyman.dev","enceladus.local","local","kubernetes.docker.internal"]).Root-causing the single real failure surfaced one genuine product bug (error shape) and one non-portable test. Both fixed. node-suite dns: 5/6 → 6/6, zero regressions.
Root causes fixed
1.
dns.resolve*/dns.reverserejections missing.syscalland.hostname(real bug)A caught
dns.resolve4error exposed only.code("ESERVFAIL"). Node's c-ares errors also carrye.syscall === "queryA"ande.hostname === "localhost"(witherrnoleftundefined);dns.reverseerrors carrysyscall === "getHostByAddr".Before / after (this machine SERVFAILs
localhostA-queries):dns.rs: newdns_query_error_valueregisters code + syscall + hostname on the message StringHeader (mirrors the existing.codeside-table path);resolve_error_value/reverse_error_valueroute through it.node_submodules/diagnostics.rs: newERROR_MESSAGE_HOSTNAMEStable +register_error_hostname/error_hostname_for_message, paralleling the syscall/path/dest tables.object/field_get_set.rs: new.hostnameError getter arm (mirrors.path/.syscall). The user-assigned-prop path is consulted before this arm, so a user-seterr.hostnamestill wins (verified against node).2.
imports/default-export.tsasserted an unportable result (test bug)The test did
const r = await resolver.resolve4("localhost")and asserted an array.resolve4queries the configured nameserver directly — it does not consult/etc/hosts— solocalhostyields an A record on some resolvers andESERVFAIL/ENOTFOUNDon others. On a SERVFAIL machine node itself aborts on the unhandled rejection, so the assertion can't pass regardless of Perry. Rewrote it to print array-or-error-code — the identical environment-robust record-or-error approach #5040 already applied to the siblingdns/resolve/localhost.ts. No product behavior was papered over: Perry already threw the correctESERVFAIL; the fix above just completes that error's shape.node-suite dns: before → after
All six: constants/error-aliases, imports/default-export, lookup/loopback, resolve/localhost, settings/default-result-order, settings/servers — PASS.
Regression check (zero regressions)
Killed: 9— re-runningnet/socket/type-of-servicecleanly gives byte-identical node/perry output. Both read onlyerr.code/.name/.message, never.hostname/.syscall, so they're untouched by this change.)err.hostname/err.pathand a plain error's.hostname/.syscallall match node exactly.perry-runtimedns_resolverunit tests: 3/3 pass.Files
crates/perry-runtime/src/dns.rscrates/perry-runtime/src/node_submodules/diagnostics.rscrates/perry-runtime/src/object/field_get_set.rstest-parity/node-suite/dns/imports/default-export.tsPer repo policy, no
Cargo.toml/CLAUDE.md/CHANGELOG.mdedits (maintainer folds version + changelog at merge).Summary by CodeRabbit
New Features
Tests