MongoServerSelectionError: por que o MongoDB não conecta

MongoServerSelectionError significa que o driver não encontrou nenhum servidor MongoDB disponível dentro do prazo, 30 segundos por padrão. As causas mais comuns são host errado, servidor parado, firewall ou lista de IPs bloqueando e DNS.

Atualizado em 7 min de leitura

Objetivos de aprendizado

Depois de ler este artigo, você vai conseguir:

  • Ler a mensagem do MongoServerSelectionError e saber o que cada parte indica
  • Diagnosticar a causa com um script curto, mongosh e testes de rede
  • Corrigir host, firewall, lista de IPs, DNS, TLS e replica set
Nesta página

Você sobe a aplicação, ela fica parada alguns segundos e então cai com MongoServerSelectionError. O nome assusta, mas a mensagem quer dizer uma coisa simples: o driver procurou um servidor MongoDB para conversar e não achou nenhum que respondesse a tempo. A conexão nem começou, então não adianta mexer em consultas, índices ou esquemas.

Os exemplos abaixo usam o driver oficial mongodb para Node.js e valem também para o Mongoose, que usa esse driver por baixo. Se você ainda está montando a conexão do zero, comece por como conectar MongoDB ao Node.js.

serverSelectionTimeoutMSLê a stringlista de hosts1Resolve o DNScada nome2ENOTFOUNDnome não resolveAbre TCP e TLSem cada host3ECONNREFUSEDou firewall em silêncioPergunta o papelprimário ou secundário4ReplicaSetNoPrimarynomes internosMongoServerSelectionErrornenhum host serviu a tempo
O erro diz que nenhum host passou por todas as etapas antes do prazo; a etapa que falhou aponta a causa.

Como é a mensagem de erro?#

O texto depois dos dois-pontos é a parte que importa. Estas são mensagens reais do driver:

MongoServerSelectionError: connect ECONNREFUSED 127.0.0.1:27017
MongoServerSelectionError: connect ECONNREFUSED ::1:27017, connect ECONNREFUSED 127.0.0.1:27017
MongoServerSelectionError: getaddrinfo ENOTFOUND db.exemplo.internal
MongoServerSelectionError: Server selection timed out after 30000 ms

Cada uma aponta para um lugar diferente:

  • ECONNREFUSED: o endereço existe, mas nada aceitou a conexão naquela porta. O servidor está parado, escuta em outra interface ou você está no host errado.
  • ENOTFOUND: o nome do host não resolveu no DNS. Erro de digitação, nome interno que só existe em outra rede ou variável de ambiente com valor antigo.
  • Server selection timed out: os pacotes saíram e nada voltou. É o padrão de firewall, lista de IPs bloqueando ou endereço inalcançável.

No Mongoose, o erro se chama MongooseServerSelectionError. Quando o destino é um cluster do MongoDB Atlas e nenhum servidor responde, ele troca a mensagem por esta:

MongooseServerSelectionError: Could not connect to any servers in your MongoDB Atlas cluster. One common reason is that you're trying to access the database from an IP that isn't whitelisted. Make sure your current IP address is on your Atlas cluster's IP whitelist: https://www.mongodb.com/docs/atlas/security-whitelist/

No Python, o equivalente do PyMongo é pymongo.errors.ServerSelectionTimeoutError, com a descrição da topologia no fim da mensagem.

O que o driver tenta fazer antes de desistir?#

O driver não abre uma conexão e pronto. Ele lê a lista de hosts da string de conexão, resolve cada nome no DNS, abre TCP (e TLS, se ativado) em cada um e pergunta ao servidor qual é o papel dele: primário, secundário ou servidor isolado. Só então escolhe um servidor adequado para a operação. Esse processo é a seleção de servidor.

Se nenhum host serve dentro de serverSelectionTimeoutMS, a operação falha. O padrão é 30000 ms, por isso o erro costuma aparecer meio minuto depois. Em replica sets há uma regra extra: os nomes de host na string precisam bater com os da configuração do replica set, e o driver precisa alcançar os membros por esses nomes. Entenda os termos em coleções, clusters e replica sets.

Duas consequências práticas: o erro diz pouco sobre o banco em si, e encurtar o prazo ajuda no diagnóstico. Com serverSelectionTimeoutMS: 5000, você espera 5 segundos em vez de 30 a cada tentativa.

Como diagnosticar a causa?#

Comece pelo próprio driver. O erro traz em reason a topologia que ele enxergou, com o estado de cada host. Este script imprime tudo isso:

javascript
// diagnostico.mjs
import { MongoClient } from "mongodb";

const uri = process.env.MONGODB_URI;
if (!uri) throw new Error("Defina a variável MONGODB_URI");

const client = new MongoClient(uri, { serverSelectionTimeoutMS: 5000 });

try {
  await client.db("admin").command({ ping: 1 });
  console.log("Conectou: o servidor respondeu ao ping");
} catch (erro) {
  console.error(`${erro.name}: ${erro.message}`);
  // erro.reason descreve a topologia que o driver enxergou
  console.error("Topologia:", erro.reason?.type);
  for (const [host, servidor] of erro.reason?.servers ?? []) {
    console.error(`- ${host}: ${servidor.type} ${servidor.error?.message ?? ""}`);
  }
  process.exitCode = 1;
} finally {
  await client.close();
}

Rode com MONGODB_URI="mongodb://..." node diagnostico.mjs na mesma máquina onde a aplicação falha. Uma topologia ReplicaSetNoPrimary (ou Unknown, quando a string tem um único host) com todos os hosts Unknown indica que nenhum servidor respondeu.

Depois, separe rede de aplicação com ferramentas fora do Node.js. Os três comandos abaixo respondem, nesta ordem: o nome resolve? A porta está aberta a partir desta máquina? O servidor responde com a mesma string?

bash
nslookup db.exemplo.com
nc -vz db.exemplo.com 27017
mongosh "$MONGODB_URI" --eval "db.runCommand({ ping: 1 })"

No PowerShell, Test-NetConnection db.exemplo.com -Port 27017 substitui o nc. Se o mongosh também falha, o problema não está no seu código.

Por que aparece ECONNREFUSED?#

Da causa mais comum à menos comum:

  1. A string aponta para localhost fora do seu computador. No seu PC havia um MongoDB local; no servidor ou no container, localhost é a própria máquina, onde não há banco. É a causa clássica de "funciona aqui, não funciona em produção". Confira também se o código tem um valor reserva como process.env.MONGODB_URI || "mongodb://localhost:27017": se a variável não foi definida, ele cai em localhost sem avisar. Veja o que são variáveis de ambiente.
  2. O servidor está parado. Verifique o processo mongod ou o container do banco e leia o log dele.
  3. O servidor escuta só em localhost. O mongod aceita conexões apenas em localhost por padrão. Para acessar de outra máquina, ele precisa escutar na interface de rede certa (net.bindIp), de preferência a interna, protegido por firewall e autenticação.
  4. IPv6 contra IPv4. Nas versões recentes do Node.js, localhost pode resolver primeiro para ::1, e o Node tenta os dois endereços, por isso a mensagem lista ::1 e 127.0.0.1. Se o banco escuta só em IPv4, use 127.0.0.1 na string ou a opção family: 4.

Uma conexão recusada em outros bancos segue a mesma lógica: veja conexão recusada no banco de dados.

Por que dá timeout na seleção de servidor?#

Timeout quer dizer que ninguém respondeu, nem para recusar. As causas típicas:

  • Lista de IPs do provedor. O MongoDB Atlas só aceita conexões de endereços na lista de acesso do projeto. Adicione o IP público de onde a aplicação sai. IPs residenciais mudam com o tempo, então um acesso que funcionava ontem pode parar hoje.
  • Firewall. A porta (27017 por padrão) está fechada no servidor do banco, no grupo de segurança da nuvem ou na rede de saída da sua aplicação. Abra só a porta do banco e só para quem precisa.
  • Replica set com nomes internos. O driver conecta no primeiro host, recebe a lista de membros com nomes que só existem dentro da rede do banco (como nomes de container) e não consegue alcançá-los. A topologia fica ReplicaSetNoPrimary. Corrija os nomes na configuração do replica set ou, para testar um único membro, use directConnection=true.
  • TLS desencontrado. Se o servidor exige TLS e o cliente não o usa (ou o contrário), a conversa inicial não fecha e o driver pode esperar até o fim do prazo. Veja a próxima seção.

E quando o erro envolve DNS ou TLS?#

Strings mongodb+srv:// não listam hosts. O driver busca um registro SRV e um registro TXT no DNS para descobrir os servidores e as opções. Quando essa busca falha, o erro aparece antes da seleção, com outro texto:

Error: querySrv ENOTFOUND _mongodb._tcp.cluster0.exemplo.mongodb.net

Confira o nome do cluster copiado do provedor e teste a resolução com nslookup -type=SRV _mongodb._tcp.cluster0.exemplo.mongodb.net. Alguns DNS de provedores de internet e VPNs falham com registros SRV; trocar o resolvedor da máquina costuma resolver. Para entender o caminho da consulta, leia o que é DNS.

Com mongodb+srv://, o TLS fica ativado automaticamente. Com mongodb://, ele vem desligado (tls=false) e você precisa adicionar tls=true se o servidor exige. Servidores com certificado próprio pedem tlsCAFile apontando para a autoridade certificadora. No Mongoose, uma mensagem que fala em SSL indica exatamente esse desencontro. O básico de certificados está em o que é SSL/TLS.

Como evitar que o erro volte?#

  • Falhe cedo. Faça um ping na inicialização e encerre o processo com uma mensagem clara se ele falhar, em vez de deixar cada requisição esperar 30 segundos.
  • Valide a variável. Pare a aplicação se MONGODB_URI estiver vazia, sem valor reserva para localhost.
  • Use um único cliente. Um MongoClient por processo, reutilizado em tudo. Criar um cliente por requisição esgota conexões e gera outros erros, como too many connections.
  • Não abra o banco para o mundo. Liberar 0.0.0.0/0 faz o erro sumir, mas expõe o banco a qualquer endereço. Prefira a rede interna ou o IP de saída da aplicação.

Como fazer isso na Square Cloud#

A Square Cloud oferece hospedagem de MongoDB a partir do plano Standard (o Hobby não inclui bancos). O banco fica pronto em segundos, no mesmo datacenter das aplicações, com latência média de cerca de 1 ms. Ele é um nó único (standalone, sem replica set) e exige TLS. São esses dois pontos que mais explicam este erro aqui.

Para evitar as causas mais comuns:

  1. Copie a URL de conexão completa que o painel entrega e não acrescente replicaSet: num nó único, esse parâmetro faz o driver esperar um primário que não existe.
  2. Baixe o certificado no painel e passe tls: true, tlsCAFile com a CA e tlsCertificateKeyFile com o .pem, porque o cliente também apresenta o certificado.
  3. Defina MONGODB_URI como variável de ambiente da aplicação, no painel, na API, na CLI ou no VS Code. A mudança vale no próximo restart, então reinicie a aplicação depois de alterar a variável.
  4. Use um único MongoClient no código, sem valor reserva para localhost, e rode o script de diagnóstico acima. O banco aceita conexões de fora, então o script também roda na sua máquina.

Se a aplicação usa um MongoDB de outro provedor com lista de IPs, lembre que ela sai por IPv4 dinâmico, sem IP fixo para liberar. Para recuperar dados, você tira snapshots manuais quando quiser, e todo plano com bancos inclui também um snapshot automático diário. Dá para restaurar um snapshot no mesmo banco, em outro do mesmo motor ou num banco novo. Veja os detalhes em hospedagem de MongoDB.

Hospedagem de bancos

MongoDB, PostgreSQL, MySQL e Redis no mesmo datacenter do app

Saiba mais

Perguntas frequentes

O que é o MongoServerSelectionError?

É o erro que o driver do MongoDB lança quando não consegue escolher um servidor para a operação dentro de serverSelectionTimeoutMS. Ele indica que a conexão nem chegou a acontecer, então o problema está na rede, no endereço ou no servidor.

Por que o erro aparece depois de 30 segundos?

Porque o padrão de serverSelectionTimeoutMS é 30000 ms. O driver tenta descobrir os servidores durante esse tempo e só desiste no fim. Você pode reduzir esse valor para o erro aparecer mais cedo.

Funciona no meu computador, mas não no servidor. Por quê?

Quase sempre a string de conexão aponta para localhost ou a variável de ambiente não foi definida no servidor. Em outra máquina, localhost é a própria máquina, onde não existe MongoDB rodando.

Liberar 0.0.0.0/0 no MongoDB Atlas resolve?

Resolve o bloqueio por IP, mas deixa o cluster aceitando conexões de qualquer endereço, protegido só por usuário e senha. Prefira liberar apenas o IP de saída do servidor onde a aplicação roda.

Senha errada causa MongoServerSelectionError?

Em geral, não. Senha ou usuário errados costumam gerar um MongoServerError com Authentication failed. Se o erro é de seleção de servidor, procure primeiro problemas de rede, endereço ou DNS.

Próximo artigoECONNREFUSED: banco de dados recusando conexãoECONNREFUSED significa que nada está escutando no host e na porta do banco. Veja as causas (servidor parado, localhost, porta, bind) e como corrigir cada uma.

Mais em Bancos de dados

Ver todos os 24 artigos