Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error ECONNREFUSED when connecting to database #313

Closed
OliverMoscow opened this issue Nov 4, 2022 · 6 comments
Closed

Error ECONNREFUSED when connecting to database #313

OliverMoscow opened this issue Nov 4, 2022 · 6 comments

Comments

@OliverMoscow
Copy link

Expected Behavior

Couchdb nano should connect to database.

Current Behavior

My couchdb server is running at localhost:5984. curl requests from terminal work fine.

In a next.js api endpoint:

const nano = require("nano")(`http://${user}:${pass}@localhost:5984`);
const db = nano.db.use("patients")
db.info().then(console.log)

when I run this I get:

error - unhandledRejection: Error: error happened in your connection
    at responseHandler (/Users/omoscow/Desktop/couch-test/node_modules/nano/lib/nano.js:137:16)
    at /Users/omoscow/Desktop/couch-test/node_modules/nano/lib/nano.js:427:13
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)

Possible Solution

Steps to Reproduce (for bugs)

  1. Create a fresh next.js application with npx create-next-app@latest
  2. npm install nano
  3. In the hello.ts file type:
const nano = require("nano")(`http://admin:couchhie8394@localhost:5984`);
const db = nano.db.use("patients")
db.info().then(console.log)
  1. npm run dev

Context

Your Environment

  • Version used: 10.1.0
  • Browser Name and version: Chrome 106
  • Operating System and version (desktop or mobile): Mac OS Monterey
  • Link to your project:
@glynnbird
Copy link
Contributor

My variation on your test script works just fine:

const nano = require("nano")(process.env.COUCH_URL);
const db = nano.db.use("mydb")

const main = async () => {
  const i = await db.info()
  console.log(i)
}

main()

@AdrianoFerrari
Copy link

I had the same issue (curl and other ways of connecting with CouchDB worked fine, nano failed with ECONNREFUSED).

I was using Node 18. Based on this SO answer I downgraded to Node 16 and it worked.

@glynnbird
Copy link
Contributor

glynnbird commented Nov 19, 2022 via email

@glynnbird
Copy link
Contributor

Just tried with 18.12.1 and it worked fine when connecting to a remote CouchDB API over https but failed when connecting to a local CouchDB over http. I'm going to investigate that further. As @AdrianoFerrari notes, changing to Node 16 fixes the problem.

I've confirmed the same happens with just plain old axios e.g

  axios.request({url: 'http://localhost:5984/mydb', method: 'get'})

so it's nothing special about Nano per se.

@glynnbird
Copy link
Contributor

glynnbird commented Nov 21, 2022

It appears to be to do with the way that "localhost" is interpreted.

In Node 16, localhost ===> 127.0.0.1
In Node 18, localhost ===> ::1, which is an IPv6 address

Note that in a default Mac /etc/hosts file there are two references to localhost:

127.0.0.1          localhost
::1                localhost

So it appears that in Node 18+, it's preferring the IPv6 option.

i.e. if you change your code to

const nano = require("nano")(`http://${user}:${pass}@127.0.0.1:5984`);

then it'll work.

@glynnbird
Copy link
Contributor

glynnbird commented Nov 21, 2022

So this is down to how Node.js resolves DNS hostnames.

In Node v16, calling the built-in function dns.lookup returns 127.0.01 and in Nodev18 it returns ::1, the IPv6 equivalent.

Given a URL with a localhost hostname, Nano will inevitably behave differently between Node versions 16 and 18 as Node's DNS resolution function has changed to prefer the IPv6 address first. A Mac's /etc/hosts file contains entries like:

127.0.0.1          localhost
::1                localhost

CouchDB doesn't listen on IPv6 addresses, as by default it's bound to 127.0.0.1 and changing this to 0.0.0.0 will only bind it to all IPv4 addresses.

There are a number of solutions:

  1. Use 127.0.0.1 instead of localhost in your URLs. This forces IPv4 and obviously doesn't require DNS resolution.
  2. Use a domain name instead of localhost. Create an entry in your /etc/hosts like 127.0.0.1 my.pretend.host and use that your hostname in the URL you feed to Nano.
  3. Remove the ::1 localhost entry from your /etc/hosts file.
  4. Stick to Node v16.
  5. Make CouchDB bind to an IPv6 address by changing bind_address = ::1 in couchdb.ini. You can then do curl 'http://USER:PASS@[::1]:5984/.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants