DNS resolution paths on Linux
“Why does dig work but the application fail” is a weekly question. The answer is that they are not doing the same thing.
dig talks to a server. Your program talks to glibc.
dig sends a DNS query to a nameserver and prints the reply. An application calls getaddrinfo(), which consults /etc/nsswitch.conf and may never send a DNS packet at all.
$ grep hosts /etc/nsswitch.conf
hosts: files mdns4_minimal [NOTFOUND=return] dns
That [NOTFOUND=return] ends the lookup before dns is reached for anything ending in .local. dig is oblivious to all of this.
Use the same path the program uses
getent hosts example.com # goes through nsswitch
getent ahostsv4 example.com # IPv4 only
Then there is systemd-resolved
If /etc/resolv.conf points at 127.0.0.53, the real configuration is elsewhere:
resolvectl status
resolvectl query example.com
Per-interface DNS, split-horizon domains, and DNSSEC validation all live there and none of it shows up in resolv.conf. A dig @8.8.8.8 that succeeds proves only that 8.8.8.8 is reachable.