For some years I have been seeing problems of nodejs based applications that do not work in IPv6 only networks. More recently, I again found a situation in which a nodejs based application does not even install, if you try to install it in an IPv6 only network.

As the situation is not just straight forward, I started to collect information about it on this website.

The starting point

I wanted to install etherpad-lite and it failed with the following error:

174 error request to https://registry.npmjs.org/express-session/-/express-session-1.17.1.tgz failed, reason: connect EHOSTUNREACH 104.16.25.35:443

The message connect EHOSTUNREACH 104.16.25.35:443 already cleary points to the problem: npm is trying to connect via IPv4 on an IPv6 only VM. This cleary cannot work.

A bug in NPM?

My first suspicion was that it must be a bug in npm. But on Twitter I was told that npm should work in IPv6 only networks. That's strange. However it turns out that somebody else had this problem before and it seems to be specific to using npm on Alpine Linux.

A bug in Alpine Linux?

Alpine Linux is currently the main distribution that I use. Not because of the small libc called musl, but because the whole system works straight forward. Correct. And easy to use. But what does that have to do with etherpad-lite failing to install in an IPv6 only network?

It turns out that there is a difference between musl and glibc in the default behaviour of getaddrinfo(), which is used to retrieve DNS results from the operating system.

A bug in musl libc?

I got in touch with the developers of musl and the statement is rather easy: musl is behaving according to the spec and the caller, in this context nodejs, cannot just use the first result, but has to potentially try all results.

A DNS or a design bug?

And at this stage the problem gets tricky. Let's revise again what I wanted to do and why we are so deep into the rabbit hole.

I wanted to install etherpad-lite, which uses resources from registry.npmjs.org. So npm wants to connect via HTTPS to registry.npmjs.org and download a file. To achieve this, npm has to find out which IP address registry.npmjs.org has. And for this it is doing a DNS lookup.

So far, so good. Now the trouble begins:

A DNS lookup can contain 0, 1 or many answers.

And in case of the libc call getaddrinfo, the result is a list of IPv6 and IPv4 addresses, potentially 0 to many of each.

So an application that "just wants to connect somewhere", cannot just take the first result.

A bug in nodejs?

The assumption at this point is that nodejs only takes the first result from DNS and tries to connect to it. However so far I have not been able to spot the exact source code location to support that claim.

Stay tuned...