Aplikasi gagal menyambung ke MongoDB selalu terdeteksi pada menit pertama: log dipenuhi pesan galat yang sama berulang-ulang, dan semua fitur yang menyentuh database ikut berhenti. Pesan seperti MongoNetworkError: connect ECONNREFUSED terasa seperti teka-teki bila kita belum tahu cara membacanya, padahal hampir semua kasus berasal dari segelintir penyebab: server tidak berjalan, port atau URI salah tulis, DNS gagal, atau jaringan yang memblokir. Chapter ini mereproduksi tiap galat itu di mesin latihan dengan cara yang aman, membedah artinya, lalu menutup dengan tabel rujukan gejala-penyebab-solusi.

Peta materi Chapter ini:

  • Tiga kelas galat koneksi dan lapisan tempatnya terjadi.
  • Mereproduksi ECONNREFUSED, lalu memverifikasi port dari shell OS dengan curl.
  • Server selection timeout, kegagalan DNS SRV, dan URI yang salah tulis.
  • Peran bindIp dan firewall, plus verifikasi koneksi dari dalam mongosh.

Membaca Kelas Galat #

Sebelum menyentuh server, baca dulu nama kelas galatnya. mongosh dan semua driver resmi memakai penamaan yang konsisten, dan nama itu langsung menunjuk lapisan yang bermasalah:

Kelas galatLapisanPertanyaan yang dijawab
MongoNetworkErrorTransport TCP/OSKoneksi ke satu host tertentu gagal dibangun?
MongoServerSelectionErrorDriver/topologiTidak ada server yang memenuhi syarat dalam batas waktu?
MongoParseError, MongoRuntimeErrorConnection stringURI-nya sendiri sudah valid sebelum mencoba tersambung?

Aturan bacanya: galat parse diperbaiki di URI, galat network diperiksa di level sistem operasi, galat selection berarti beberapa host bermasalah sekaligus atau syarat koneksi (read preference, TLS) tidak terpenuhi. Pesan lengkap di bawah nama kelas menentukan langkah berikutnya — kita bedah satu per satu.

Port yang Mati: ECONNREFUSED #

Bentuk paling klasik: mongod tidak berjalan, atau berjalan di port lain. Kita reproduksi dengan mengarahkan mongosh ke port yang pasti kosong:

bash
mongosh --quiet --port 28099 --eval 'db.adminCommand({ping:1})'

Output yang Dihasilkan:

text
MongoNetworkError: connect ECONNREFUSED 127.0.0.1:28099

Sistem operasi menjawab dengan tegas: tidak ada proses yang mendengarkan port 28099, sehingga kernel mengirim balasan penolakan dan mongosh melaporkannya sebagai ECONNREFUSED. Galat ini justru kabar baik — host jelas terjangkau dan jawabannya pasti, jadi tersisa dua tersangka: mongod mati atau port salah tulis. Sebelum menyalakan ulang apa pun, verifikasi port dari shell OS:

bash
curl -v telnet://127.0.0.1:28099

Output yang Dihasilkan:

text
*   Trying 127.0.0.1:28099...
* connect to 127.0.0.1 port 28099 from 127.0.0.1 port 48148 failed: Connection refused
* Failed to connect to 127.0.0.1 port 28099 after 0 ms: Could not connect to server
* closing connection #0

Bandingkan dengan port yang hidup — opsi -m 2 memberi batas dua detik agar curl berhenti sendiri:

bash
curl -v -m 2 telnet://127.0.0.1:27017

Output yang Dihasilkan:

text
*   Trying 127.0.0.1:27017...
* Connected to 127.0.0.1 (127.0.0.1) port 27017
* Time-out
* shutting down connection #0

Dua hal perlu dicermati. Angka 48148 adalah port sementara milik curl sendiri — nilainya berubah tiap eksekusi dan bukan bagian dari diagnosis. Baris Time-out pada ujian kedua juga bukan kegagalan: mode telnet menunggu data setelah tersambung, sementara mongod tidak mengirim apa pun sebelum klien berbicara; baris Connected to ... adalah bukti port terbuka. Kode exit-nya pun berbeda: 7 (gagal tersambung) versus 28 (berhenti karena batas waktu).

Timeout, DNS SRV, dan URI yang Salah #

Kebalikan dari ECONNREFUSED adalah host yang tidak menjawab sama sekali. Kita reproduksi dengan IP pribadi yang tidak ter-route dan batas waktu pemilihan server yang pendek:

bash
mongosh --quiet "mongodb://10.255.255.1:27017/?directConnection=true&serverSelectionTimeoutMS=3000" --eval 'db.adminCommand({ping:1})'

Output yang Dihasilkan:

text
MongoServerSelectionError: Server selection timed out after 3000 ms

Driver mencoba membangun koneksi TCP dan tidak menerima jawaban apa pun — bukan penolakan — sampai batas serverSelectionTimeoutMS (bawaan 30 detik) terlampaui. Penyebab umumnya: host mati total, firewall yang membungkam paket, atau jalur VPN yang putus. Firewall yang menolak menghasilkan ECONNREFUSED yang cepat; firewall yang membungkam menghasilkan timeout yang lambat.

Dua galat berikutnya terjadi bahkan sebelum koneksi dicoba. Skema mongodb+srv memicu pencarian DNS record SRV, dan bila domainnya tidak ada:

bash
mongosh --quiet "mongodb+srv://cluster0.example.com" --eval 'db.adminCommand({ping:1})'

Output yang Dihasilkan:

text
Error: querySrv ENOTFOUND _mongodb._tcp.cluster0.example.com

Driver mencari record _mongodb._tcp.cluster0.example.com dan DNS menjawab “tidak ada” (ENOTFOUND). Perbaikannya ada di URI atau di DNS-nya: pastikan nama cluster ditulis lengkap, resolver berfungsi, dan record SRV memang sudah dibuat. Terakhir, opsi URI yang salah tulis:

bash
mongosh --quiet "mongodb://127.0.0.1:27017/?foo=bar" --eval 'db.adminCommand({ping:1})'

Output yang Dihasilkan:

text
MongoParseError: option foo is not supported

Galat parse murni soal teks URI dan tidak pernah menyentuh jaringan — port yang bukan angka atau skema yang salah menghasilkan keluarga galat serupa (Unable to parse ... with URL). Perbaikannya cepat: koreksi URI, jangan menyalakan ulang server.

bindIp, Firewall, dan Verifikasi Koneksi #

Satu penyebab yang sering terlewat: mongod berjalan sehat tetapi hanya mendengarkan satu interface. Konfigurasi bawaan (dan server latihan kita) memuat bindIp: 127.0.0.1, artinya koneksi hanya diterima dari mesin yang sama; koneksi dari komputer lain akan timeout atau ditolak tergantung firewall. Memperluas akses berarti mengubah bindIp, membuka port di firewall, dan menyalakan TLS serta authentication — dibahas di Section Keamanan.

Setelah koneksi berhasil, dua pemeriksaan ringkas memverifikasi bahwa sasarannya memang benar. Perintah hello mengonfirmasi topologi dari sudut pandang klien:

js
use latihan_trouble
const hello = db.hello()
print("setName: " + hello.setName)
print("primary: " + hello.primary)
print("isWritablePrimary: " + hello.isWritablePrimary)

Output yang Dihasilkan:

text
switched to db latihan_trouble

setName: rs0

primary: 127.0.0.1:27017

isWritablePrimary: true

Baris demi baris: setName memastikan replica set yang dituju sudah benar, primary menunjuk anggota penerima write, dan isWritablePrimary: true menegaskan node ini boleh menerima write. Untuk gejala “kadang connect, kadang gagal”, penghitung koneksi server adalah tempat lihat berikutnya:

js
db.adminCommand({ ping: 1 }).ok
db.serverStatus().connections

Output yang Dihasilkan:

text
1
{
  current: 5,
  available: 404,
  totalCreated: 12245,
  rejected: 0,
  active: 1,
  queuedForEstablishment: 0,
  establishmentRateLimit: { rejected: 0, exempted: 0, interruptedDueToClientDisconnect: 0 },
  threaded: 5,
  exhaustIsMaster: Long('0'),
  exhaustHello: Long('0'),
  awaitingTopologyChanges: Long('0'),
  loadBalanced: 0,
  priority: 0
}

Angka pasti berbeda tiap eksekusi, tetapi relasinya tetap: current koneksi terbuka saat ini, available sisa kapasitas, totalCreated akumulasi sejak server menyala. Bila current terus merambat naik tanpa turun, aplikasi membuka koneksi tanpa menutupnya — arah perbaikannya ada di connection pool aplikasi (Chapter Connection Pooling).

Tabel Rujukan Cepat #

GejalaPenyebab umumSolusi pertama
connect ECONNREFUSEDmongod mati atau port salahPeriksa proses dan port; uji dengan curl -v telnet://host:port
Server selection timed outHost tidak menjawab; firewall membungkam paketUji jalur jaringan/VPN; turunkan serverSelectionTimeoutMS agar gagal cepat
querySrv ENOTFOUNDDomain atau record SRV tidak adaKoreksi nama cluster di URI; periksa resolver DNS
option ... is not supported / Unable to parse ... with URLOpsi, port, atau skema URI salah tulisKoreksi format mongodb://host:port dan daftar opsinya
Koneksi dari jauh selalu timeoutbindIp hanya 127.0.0.1Ubah bindIp; buka port firewall dengan TLS dan authentication aktif
current merangkak mendekati availableAplikasi membocorkan koneksiAudit connection pool; pastikan klien menutup koneksi

Rangkuman #

  • Nama kelas galat menunjuk lapisannya: parse berarti URI, network berarti transport, selection berarti topologi.
  • ECONNREFUSED adalah penolakan cepat dari OS — periksa proses dan port; timeout berarti tidak ada jawaban — periksa host, firewall, atau jalur jaringan.
  • curl -v telnet://host:port memverifikasi port tanpa kredensial dalam satu baris.
  • Skema mongodb+srv bergantung pada record SRV; ENOTFOUND berarti masalah selesai sebelum koneksi dimulai.
  • Setelah terhubung: hello() memverifikasi topologi, ping memverifikasi respons, serverStatus().connections mengawasi kelebihan koneksi.