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
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.
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 msCada 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:
// 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?
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:
- 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 comoprocess.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. - O servidor está parado. Verifique o processo
mongodou o container do banco e leia o log dele. - O servidor escuta só em localhost. O
mongodaceita 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. - IPv6 contra IPv4. Nas versões recentes do Node.js,
localhostpode resolver primeiro para::1, e o Node tenta os dois endereços, por isso a mensagem lista::1e127.0.0.1. Se o banco escuta só em IPv4, use127.0.0.1na string ou a opçãofamily: 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, usedirectConnection=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.netConfira 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
pingna 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_URIestiver vazia, sem valor reserva para localhost. - Use um único cliente. Um
MongoClientpor 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/0faz 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:
- 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. - Baixe o certificado no painel e passe
tls: true,tlsCAFilecom a CA etlsCertificateKeyFilecom o.pem, porque o cliente também apresenta o certificado. - Defina
MONGODB_URIcomo 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. - Use um único
MongoClientno 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
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.
Mais em Bancos de dados
Ver todos os 24 artigos- Quanto custa um banco de dados na nuvem?Um banco de dados na nuvem custa de zero a centenas de dólares por mês. Veja o que define o preço: instância, disco, tráfego, snapshots e como estimar o seu.
- Como hospedar um banco de dados (e conectar sua aplicação)Para hospedar um banco de dados, escolha o motor, crie a instância, guarde a string de conexão em variável de ambiente e teste a conexão. Veja o passo a passo.
- O que é Redis e para que serveRedis é um banco de dados em memória que guarda pares chave-valor e estruturas de dados. Veja como funciona, para que serve e quando não usar.
- Como fazer backup do banco de dados (MySQL, PostgreSQL, MongoDB)Faça backup de MySQL, PostgreSQL e MongoDB com mysqldump, pg_dump e mongodump, e restaure o dump. Veja os comandos, como verificar e os erros comuns.