Troubleshooting
What to check when a name does not resolve, and how to undo everything by hand.
A name does not resolve
Work down this list. Each step tells you which of the three moving parts is missing.
- 1Is the app running? The forwarder exits by itself when the app stops, so
myapp.testresolves but nothing answers. Look for the patchbay icon in the menu bar. - 2Is the hosts entry there?
grep -A20 'localhost-aliases' /etc/hostsshould show your hostname inside the marker block. - 3Is the address on lo0?
ifconfig lo0 | grep 'inet 127.0.0'should list the alias's address. A reboot clears these; relaunching the app re-adds them behind one prompt. - 4Is anything listening on the target port?
curl -sv http://127.0.0.1:3000— if that fails, the alias is fine and your dev server is not up. - 5Is DNS cached?
sudo dscacheutil -flushcacheandsudo killall -HUP mDNSResponder. The app does this for you after every apply, but a browser keeps its own cache too.
the one-line check
curl -sv http://myapp.test 2>&1 | head -20
It resolves, but the browser gets nothing
The forwarder connects to 127.0.0.1:<port> specifically. A dev server bound only to IPv6 ::1, or only to an external interface, will not be reachable — bind it to 127.0.0.1 or 0.0.0.0. lsof -nP -iTCP:3000 -sTCP:LISTEN shows which address it actually took.
If the dashboard shows no server for an alias, that is exactly this: the name and the address are in place, and nothing is listening on the port behind them.
https:// does not work
It cannot, for project aliases, and this is not a bug to be fixed. The forwarder moves raw bytes and never sees the traffic, so there is nothing there that could terminate TLS. Use http://. https:// is available for the dashboard alone. See how aliases work.
The TLD I typed was rejected
Three families of TLD are refused, each for a specific reason rather than a preference. The default, .test, is reserved for development by RFC 6761 and has none of these problems — see how aliases work.
.local— reserved for mDNS/Bonjour, and on macOSmDNSResponderowns it. Every lookup waits out a multicast query first: about five seconds per name, whether or not the name is in/etc/hosts. A dev URL that takes five seconds to resolve is not usable, so the app does not offer the suffix..dev,.app,.pageand the rest of the HSTS preload list — Chrome and Safari rewritehttp://tohttps://for these before the request leaves the machine. Project aliases arehttp://only, so the browser would show a TLS error instead of your app..localhost— macOS answers this suffix itself, always127.0.0.1, without reading/etc/hosts. Each alias has its own127.0.0.x, so the name would never reach it.
Settings offers test, internal, lan, home.arpa and example, and accepts anything else that is not on those three lists. Changing the TLD renames every hostname, so the next apply raises the admin prompt once.
Recovering by hand
If the app is gone, broken, or you simply do not trust it any more, you can undo everything yourself. Two things were changed and both are visible.
- 1Open
/etc/hostsas root (sudo nano /etc/hosts) and delete everything from# >>> localhost-aliases >>>to# <<< localhost-aliases <<<, markers included. Nothing outside that block was ever ours. - 2Remove each loopback address the app added:
sudo ifconfig lo0 -alias 127.0.0.2, once per address.ifconfig lo0lists them;127.0.0.1is the real loopback and must stay. - 3Flush DNS:
sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder. - 4Delete the app from
/Applicationsand, if you want the state gone too,rm -rf ~/.config/localhost-aliases.
The forwarder is running as root
~/.config/localhost-aliases/liveness — quitting or deleting the app is enough. Deleting that file has the same effect. You do not need to hunt for a process to kill.The lo0 addresses do not survive a reboot either, so a restart clears half of this for you.
Logs
Every privileged run appends to ~/Library/Logs/localhost-aliases/privileged.log, including the exact step that failed. The forwarder's own view of the world is in ~/.config/localhost-aliases/forwarder-status.json, which is written so the UI can read real state without asking for privileges.