Monday, May 12, 2014

Fixing "SocketError: getaddrinfo: Name or service not known" with Ruby's resolv-replace.rb

Update 6/3/2014: there are other advantages to using a pure-Ruby DNS implementation.

Recently we had a problem with DNS lookups for a particular API that only afflicted our Heroku-based workers (host name changed to protect the innocent):


irb(main):009:0> Socket.gethostbyname("example.net")
SocketError: getaddrinfo: Name or service not known

That line of code works fine in other places I tried, like my dev machine. The specific error had to do with a call that Ruby's net/http library was making. I filed a ticket with Heroku support using the above example, and they suggested I try using Ruby's Resolv library, something I had not encountered before. This post is a little breadcrumb to help others who may have the same problem.

Resolv uses Ruby code to do DNS lookups, instead of relying on the system's libc installation like gethostbyname does. Rather than having to monkeypatch net/http, all I had do to was add require "resolv-replace.rb" to our startup code which automatically added this fix. I never found out why the normal lookup process wasn't working on Heroku, but this worked. Thanks to the thoughtful soul who wrote resolv-replace.rb!

8 comments:

A said...

Thank you for posting this! This was incredibly helpful. After searching for things like:

ruby socketerror
and
ruby dns lookup issue

and many variations, I finally found your blog post and it helped me fix my script. Thank you!

Greg Gehrich said...

Some progress.... this changed my error from "SocketError: getaddrinfo: Name or service not known" to "SocketError (Hostname not known: .)"

This is the source of the error:

doc = Nokogiri::HTML(open(@full_web_url))

I added "require 'resolv-replace'" (without the double quotes) to the top of my action in the controller. Right place?

Mike Subelsky said...

I recommend putting that require statement into an initializer (config/initializers/requires.rb is what I usually do)

if that doesn't work, then I would try running dig and whois commands on the server in question, to see if there's something messed-up with the DNS server you are using for lookups.

Try using a different DNS server (like Google's public DNS https://developers.google.com/speed/public-dns/)

Greg Gehrich said...

Thanks for pointing me toward this solution. Turns out, it was an open with a nil url that happened on heroku, but not locally (?). Once I handled that, all is good.

Дмитрий Увин said...
This comment has been removed by the author.
Дмитрий Увин said...

I use windows with customized proxy and I get this error: "SocketError Hostname not known: api.stackexchange.com",
when I try to "run response = HTTParty.get('https://api.stackexchange.com/2.2/questions?site=stackoverflow')" in the console. Any help would be pleasant)))

Terry S said...

Brilliant. This saved me a bunch of hassle. Thank you!

eggmatters said...

I had this same issue. Unfortunately for me (or fortunately) the IP's on some external API's had changed. As usual, rule out the painfully obvious before looking further. (As you had done)