302

My server threw this today, which is a Node.js error I've never seen before:

Error: getaddrinfo EAI_AGAIN my-store.myshopify.com:443
    at Object.exports._errnoException (util.js:870:11)
    at errnoException (dns.js:32:15)
    at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:78:26)

I'm wondering if this is related to the DynDns DDOS attack which affected Shopify and many other services today. Here's an article about that.

My main question is what does dns.js do? What part of node is it a part of? How can I recreate this error with a different domain?

mikemaccana
  • 110,530
  • 99
  • 389
  • 494
ThomasReggi
  • 55,053
  • 85
  • 237
  • 424

15 Answers15

225

EAI_AGAIN is a DNS lookup timed out error, means it is a network connectivity error or proxy related error.

My main question is what does dns.js do?

  • The dns.js is there for node to get ip address of the domain(in brief).

Some more info: http://www.codingdefined.com/2015/06/nodejs-error-errno-eaiagain.html

xerq
  • 2,362
  • 1
  • 9
  • 16
212

If you get this error with Firebase Cloud Functions, this is due to the limitations of the free tier (outbound networking only allowed to Google services).

Upgrade to the Flame or Blaze plans for it to work.

enter image description here

bastien
  • 2,940
  • 1
  • 13
  • 23
  • 1
    that's right, just upgraded to pay per use blaze plan for zero cost (this carry-forward free tier data from spark) – GorvGoyl Dec 13 '19 at 21:28
  • Can you @NullPointer, elaborate the solution, i still getting errors ` Error: could not handle the request` – Alam Mar 17 '20 at 12:44
  • 1
    I have same issue and have upgraded to Blaze account but still the problem is same. I am trying using postman. – Devendra Singh May 11 '20 at 11:55
  • For some reason I've had this when trying access my credentials for SMTP via `process.env.SOMETHING`, even with the `Blaze` enabled. – Daniel Danielecki Nov 27 '20 at 15:35
  • In my case I was already on Blaze plan, just that my card had expired. – eozzy Jul 09 '21 at 03:18
54

If you get this error from within a docker container, e.g. when running npm install inside of an alpine container, the cause could be that the network changed since the container was started.

To solve this, just stop and restart the container

docker-compose down
docker-compose up

Source: https://github.com/moby/moby/issues/32106#issuecomment-578725551

Diego P. Steiner
  • 2,075
  • 1
  • 15
  • 14
  • I have a suspected issue where the network is reset on the host, and then the containers seem to have DNS errors thereafter. Is there some way to configure the containers to survive this *without* stopping them? – trademark May 14 '21 at 20:21
  • I tried `docker-compose up -d --build` and it wasn't fixed. So I guess `docker-compose down` then `docker-compose up` is the only solution – Phuong Dao Apr 15 '22 at 06:39
  • Restarting the specific docker container solved my issue as well. I think the problem is that the docker image is starting faster than my OS network is ready. Causing issues in resolving/DNS. I think containerd.service or docker.service should `Requires=network-online.target`. Or: `After=network-online.target Wants=network-online.target` OR even better maybe: `After=nss-lookup.target` – Melroy van den Berg Jul 14 '22 at 20:28
  • Exactly what was happening in my case, thanks! – bombillazo Feb 13 '23 at 02:02
26

As xerq's excellent answer explains, this is a DNS timeout issue.

I wanted to contribute another possible answer for those of you using Windows Subsystem for Linux - there are some cases where something seems to be askew in the client OS after Windows resumes from sleep. Restarting the host OS will fix these issues (it's also likely restarting the WSL service will do the same).

mikemaccana
  • 110,530
  • 99
  • 389
  • 494
17

For those who perform thousand or millions of requests per day, and need a solution to this issue:

It's quite normal to get getaddrinfo EAI_AGAIN errors when performing a lot of requests on your server. Node.js itself doesn't perform any DNS caching, it delegates everything DNS related to the OS.

You need to have in mind that every http/https request performs a DNS lookup, this can become quite expensive, to avoid this bottleneck and getaddrinfo errors, you can implement a DNS cache.

http.request (and https) accepts a lookup property which defaults to dns.lookup()

http.get('http://example.com', { lookup: yourLookupImplementation }, response => {
    // do something here with response
});

I strongly recommend to use an already tested module, instead of writing a DNS cache yourself, since you'll have to handle TTL correctly, among other things to avoid hard to track bugs.

I personally use cacheable-lookup which is the one that got uses (see dnsCache option).

You can use it on specific requests

const http = require('http');
const CacheableLookup = require('cacheable-lookup');

const cacheable = new CacheableLookup();

http.get('http://example.com', {lookup: cacheable.lookup}, response => {
    // Handle the response here
});

or globally

const http = require('http');
const https = require('https');
const CacheableLookup = require('cacheable-lookup');

const cacheable = new CacheableLookup();

cacheable.install(http.globalAgent);
cacheable.install(https.globalAgent);

NOTE: have in mind that if a request is not performed through Node.js http/https module, using .install on the global agent won't have any effect on said request, for example requests made using undici

Marcos Casagrande
  • 37,983
  • 8
  • 84
  • 98
5

The OP's error specifies a host (my-store.myshopify.com). The error I encountered is the same in all respects except that no domain is specified.

My solution may help others who are drawn here by the title "Error: getaddrinfo EAI_AGAIN"

I encountered the error when trying to serve a NodeJs & VueJs app from a different VM from where the code was developed originally.

The file vue.config.js read :

 module.exports = {
   devServer: {
     host: 'tstvm01',
     port: 3030,
   },
 };

When served on the original machine the start up output is :

App running at:
- Local:   http://tstvm01:3030/ 
- Network: http://tstvm01:3030/

Using the same settings on a VM tstvm07 got me a very similar error to the one the OP describes:

 INFO  Starting development server...
 10% building modules 1/1 modules 0 activeevents.js:183                              
      throw er; // Unhandled 'error' event
      ^

Error: getaddrinfo EAI_AGAIN
    at Object._errnoException (util.js:1022:11)
    at errnoException (dns.js:55:15)
    at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:92:26)

If it ain't already obvious, changing vue.config.js to read ...

 module.exports = {
   devServer: {
     host: 'tstvm07',
     port: 3030,
   },
 };

... solved the problem.

Martin Bramwell
  • 2,003
  • 2
  • 19
  • 35
5

I was having this issue on docker-compose. Turns out I forgot to add my custom isolated named network to my service which couldn't be found.

TLDR; Make sure, in your compose file, you have your custom-networks defined on both services that need to talk to each other.

My error looked like this: Error: getaddrinfo EAI_AGAIN minio-service. The error was coming from my server's backend when making a call to the minio-service using the minio-service hostname. This tells me that minio-service's running service, was not reachable by my server's running service. The way I was able to fix this issue is I changed the minio-service in my docker-compose from this:

  • docker-compose.yml
version: "3.8"

# ...

services:
  server:
    # ...
    networks:
      my-network:
    # ...
  minio-service:
    # ... (missing networks: section)

# ...

networks:
  my-network:

To include my custom isolated named network, like this:

  • docker-compose.yml
version: "3.8"

# ...

services:
  server:
    # ...
    networks:
      my-network:
    # ...
  minio-service:
    # ...   
    networks:
      my-network:
    # ...

# ...

networks:
  my-network:

More details on docker-compose networking can be found here.

John
  • 7,114
  • 2
  • 37
  • 57
  • I have this issue when going outside the network (=internet). However, often only during reboots. Manually restarting the docker container fixes the problem. I think Docker is starting my containers faster than my network/DNS resolver is ready to handle the requests. I think `After=network-online.target Wants=network-online.target` are missing from containerd.service or docker.service systemd configs. Or `After=nss-lookup.target` should be added – Melroy van den Berg Jul 14 '22 at 20:30
4

I started getting this error (different stack trace though) after making a trivial update to my GraphQL API application that is operated inside a docker container. For whatever reason, the container was having difficulty resolving a back-end service being used by the API.

After poking around to see if some change had been made in the docker base image I was building from (node:13-alpine, incidentally), I decided to try the oldest computer science trick of rebooting... I stopped and started the docker container and all went back to normal.

Clearly, this isn't a meaningful solution to the underlying problem - I am merely posting this since it did clear up the issue for me without going too deep down rabbit holes.

halfer
  • 19,824
  • 17
  • 99
  • 186
John Rix
  • 6,271
  • 5
  • 40
  • 46
3

This is the issue related to hosts file setup. Add the following line to your hosts file In Ubuntu: /etc/hosts

127.0.0.1   localhost

In windows: c:\windows\System32\drivers\etc\hosts

127.0.0.1   localhost
RevNoah
  • 2,344
  • 3
  • 20
  • 28
Radhe9254
  • 198
  • 1
  • 11
2

In my case the problem was the docker networks ip allocation range, see this post for details

mbesson
  • 629
  • 5
  • 24
2

In my case, connected to VPN, the error happens when running Ubuntu from inside Windows Terminal but doesn't happen when opening Ubuntu directly from Windows (not from inside the Windows Terminal)

enter image description here

2

I was getting this error after I recently added a new network to my docker-compose file.

I initially had these services:

services:
  frontend:
    depends_on:
      - backend
    ports:
      - 3005:3000
  
  backend:
    ports:
      - 8005:8000

I decided to add a new network which hosts other services I wanted my frontend service to have access to, so I did this:

networks:
  moar:
    name: moar-network
    attachable: true

services:
  frontend:
    networks:
      - moar
    depends_on:
      - backend
    ports:
      - 3005:3000
  
  backend:
    ports:
      - 8005:8000

Unfortunately, the above made it so that my frontend service was no longer visible on the default network, and only visible in the moar network. This meant that the frontend service could no longer proxy requests to backend, therefore I was getting errors like:

Error occured while trying to proxy to: localhost:3005/graphql/

The solution is to add the default network to the frontend service's network list, like so:

networks:
  moar:
    name: moar-network
    attachable: true

services:
  frontend:
    networks:
      - moar
      - default # here
    depends_on:
      - backend
    ports:
      - 3005:3000
  
  backend:
    ports:
      - 8005:8000

Now we're peachy!


One last thing, if you want to see which services are running within a given network, you can use the docker network inspect <network_name> command to do so. This is what helped me discover that the frontend service was not part of the default network anymore.

smac89
  • 39,374
  • 15
  • 132
  • 179
1

@xerq pointed correctly, here's some more reference http://www.codingdefined.com/2015/06/nodejs-error-errno-eaiagain.html

i got the same error, i solved it by updating "hosts" file present under this location in windows os

C:\Windows\System32\drivers\etc

Hope it helps!!

Mateen
  • 1,631
  • 1
  • 23
  • 27
0

I had a same problem with AWS and Serverless. I tried with eu-central-1 region and it didn't work so I had to change it to us-east-2 for the example.

Igor Janković
  • 5,494
  • 6
  • 32
  • 46
-2

Enabled Blaze and it still doesn't work?

Most probably you need to set .env from the right path, require('dotenv').config({ path: __dirname + './../.env' }); won't work (or any other path). Simply put the .env file in the functions directory, from which you deploy to Firebase.

Daniel Danielecki
  • 8,508
  • 6
  • 68
  • 94