Background
Since 2.1.0, fedify lookup validates URLs with validatePublicUrl() unless -p/--allow-private-address is given. When an error reaches the lookup command's error handler, getLookupFailureHint() in packages/cli/src/lookup.ts picks the hint to print. It recognizes private-address rejections by matching the error message (“invalid or private address”, “localhost is not allowed”) and treats everything else as a possible authorization failure. A DNS failure is also a UrlError, but its message doesn't match, so the user is told to try -a/--authorized-fetch.
#1060 added UrlError.reason to 2.0-maintenance, which tells DNS failures ("dns") apart from disallowed URLs ("disallowed"), and #1062 makes the library's own callers use it. Neither has been merged forward into 2.1-maintenance yet. Once they are, the CLI can use reason as well.
Expected behavior
getLookupFailureHint() returns a separate hint for UrlError with reason === "dns", one that points at the hostname or the network instead of at authorized fetch.
- For a
UrlError, isPrivateAddressError() requires reason === "disallowed" and keeps the message check on top of it. The message check can't go: Unsupported protocol is also "disallowed" but isn't a private address, and lookup.test.ts already tests that it doesn't get the private-address hint.
- Tests cover both reasons, using
new UrlError(…, { reason: "dns" }) directly instead of relying on real DNS.
This only covers errors that reach getLookupFailureHint(). The plain single-object lookup never does, because lookupObject() swallows the loader's error and returns null; that path is tracked in #1063. If the fix for #1063 keeps the loader's error, the same reason check should apply to that path.
Where to work
Branch off 2.1-maintenance after #1062 has been merged forward into it. The change will then be merged into 2.2-maintenance, 2.3-maintenance, and main. The hint code on main has diverged a little (describeError(), getPrivateUrlCandidate()), so expect a small conflict there.
AI disclosure
This issue was drafted with Claude Code (Claude Opus 5.5), with a style review by Codex, and reviewed and edited by a human before submission.
Background
Since 2.1.0,
fedify lookupvalidates URLs withvalidatePublicUrl()unless-p/--allow-private-addressis given. When an error reaches the lookup command's error handler,getLookupFailureHint()in packages/cli/src/lookup.ts picks the hint to print. It recognizes private-address rejections by matching the error message (“invalid or private address”, “localhost is not allowed”) and treats everything else as a possible authorization failure. A DNS failure is also aUrlError, but its message doesn't match, so the user is told to try-a/--authorized-fetch.#1060 added
UrlError.reasonto 2.0-maintenance, which tells DNS failures ("dns") apart from disallowed URLs ("disallowed"), and #1062 makes the library's own callers use it. Neither has been merged forward into 2.1-maintenance yet. Once they are, the CLI can usereasonas well.Expected behavior
getLookupFailureHint()returns a separate hint forUrlErrorwithreason === "dns", one that points at the hostname or the network instead of at authorized fetch.UrlError,isPrivateAddressError()requiresreason === "disallowed"and keeps the message check on top of it. The message check can't go:Unsupported protocolis also"disallowed"but isn't a private address, and lookup.test.ts already tests that it doesn't get the private-address hint.new UrlError(…, { reason: "dns" })directly instead of relying on real DNS.This only covers errors that reach
getLookupFailureHint(). The plain single-object lookup never does, becauselookupObject()swallows the loader's error and returnsnull; that path is tracked in #1063. If the fix for #1063 keeps the loader's error, the samereasoncheck should apply to that path.Where to work
Branch off 2.1-maintenance after #1062 has been merged forward into it. The change will then be merged into 2.2-maintenance, 2.3-maintenance, and main. The hint code on main has diverged a little (
describeError(),getPrivateUrlCandidate()), so expect a small conflict there.AI disclosure
This issue was drafted with Claude Code (Claude Opus 5.5), with a style review by Codex, and reviewed and edited by a human before submission.