Insert ditolak server dengan pesan pendek Document failed validation — dua kata yang tidak menjelaskan apa-apa tentang apa yang salah. Untungnya pesan itu bukan seluruh cerita: MongoDB menyematkan pohon rincian lengkap di field errInfo, mulai dari document mana yang ditolak sampai aturan mana yang dilanggar dan nilai apa yang dikirim. Chapter ini membangun collection dengan validator $jsonSchema, memicu dua jenis pelanggaran yang berbeda, lalu membaca struktur errInfo secara bertingkat — pola yang sama persis untuk collection production apa pun.

Peta materi Chapter ini:

  • Mereproduksi DocumentValidationFailure kode 121 beserta errInfo aslinya.
  • Membaca pohon schemaRulesNotSatisfied hingga ke consideredValue.
  • Pelanggaran required yang strukturnya berbeda dari pelanggaran properties.
  • Strategi memilih antara memperbaiki data dan memperbaiki aturan.

Reproduksi: Validator yang Menolak #

Kita buat collection pelanggan dengan tiga aturan: nama minimal dua karakter, email harus memuat simbol @, dan umur minimal 13 (angka bulat). Detail sintaks $jsonSchema sudah dibahas di Section Schema Validation — di sini fokus kita adalah sisi galatnya:

js
use latihan_trouble
db.pelanggan.drop()
db.createCollection("pelanggan", {
  validator: { $jsonSchema: {
    required: ["nama", "email"],
    properties: {
      nama: { bsonType: "string", minLength: 2 },
      email: { bsonType: "string", pattern: "^.+@.+$" },
      umur: { bsonType: "int", minimum: 13 }
    }
  }}
})

Output yang Dihasilkan:

text
switched to db latihan_trouble
true
{ ok: 1 }

Kirim satu document yang melanggar ketiga aturan properties sekaligus, dan tangkap objek galatnya dengan try/catch:

js
try {
  db.pelanggan.insertOne({ nama: "B", email: "budi#example.com", umur: 11 })
} catch (err) {
  print("code: " + err.code)
  print("message: " + err.message)
  print(JSON.stringify(err.errInfo, null, 2))
}

Output yang Dihasilkan:

text
code: 121
message: Document failed validation
{
  "failingDocumentId": "6ad40267f399b334b4a5eff3",
  "details": {
    "operatorName": "$jsonSchema",
    "schemaRulesNotSatisfied": [
      {
        "operatorName": "properties",
        "propertiesNotSatisfied": [
          {
            "propertyName": "nama",
            "details": [
              {
                "operatorName": "minLength",
                "specifiedAs": {
                  "minLength": 2
                },
                "reason": "specified string length was not satisfied",
                "consideredValue": "B"
              }
            ]
          },
          {
            "propertyName": "email",
            "details": [
              {
                "operatorName": "pattern",
                "specifiedAs": {
                  "pattern": "^.+@.+$"
                },
                "reason": "regular expression did not match",
                "consideredValue": "budi#example.com"
              }
            ]
          },
          {
            "propertyName": "umur",
            "details": [
              {
                "operatorName": "minimum",
                "specifiedAs": {
                  "minimum": 13
                },
                "reason": "comparison failed",
                "consideredValue": 11
              }
            ]
          }
        ]
      }
    ]
  }
}

Bagian atasnya pendek: kode 121 adalah nomor resmi DocumentValidationFailure, dan message-nya memang sebisanya itu. Kekuatan sesungguhnya ada di errInfo — sebuah pohon yang kita baca dari akar ke daun.

Membaca Pohon schemaRulesNotSatisfied #

Struktur errInfo selalu bertingkat sama. Kita bedah per lapisan:

  • failingDocumentId — _id document yang ditolak. Validator memeriksa document setelah _id dihasilkan, jadi nilai ini bisa dipakai mencari asal data di sistem hulu.
  • details.operatorName: "$jsonSchema" — jenis validator yang menolak; bila collection memakai aturan query biasa (bukan $jsonSchema), di sinilah bentuknya berubah.
  • schemaRulesNotSatisfied — daftar kategori aturan yang dilanggar. Pada contoh kita isinya satu kategori: properties.
  • Di dalamnya, propertiesNotSatisfied mendaftar tiap field yang gagal; untuk setiap field ada details berisi operatorName aturan (minLength, pattern, minimum), specifiedAs (aturan persisnya), reason (kenapa gagal), dan consideredValue — nilai yang dikirim aplikasi.

Dua field terakhir itu adalah pasangan diagnosis paling berharga: specifiedAs menunjukkan hukumnya, consideredValue menunjukkan buktinya. nama: "B" terbukti lebih pendek dari minLength: 2; "budi#example.com" terbukti tidak cocok dengan pola email; umur: 11 terbukti di bawah minimum: 13. Tidak ada ruang menebak — setiap klaim validator disertai nilainya.

Pelanggaran required yang Berbeda Bentuk #

Kedua jenis pelanggaran berikutnya punya struktur lain: document yang sama sekali tidak memuat field wajib tidak masuk ke propertiesNotSatisfied, melainkan ke kategori required tersendiri:

js
try {
  db.pelanggan.insertOne({ umur: 15 })
} catch (err) {
  print(JSON.stringify(err.errInfo, null, 2))
}

Output yang Dihasilkan:

text
{
  "failingDocumentId": "6ad40267f399b334b4a5eff4",
  "details": {
    "operatorName": "$jsonSchema",
    "schemaRulesNotSatisfied": [
      {
        "operatorName": "required",
        "specifiedAs": {
          "required": [
            "nama",
            "email"
          ]
        },
        "missingProperties": [
          "email",
          "nama"
        ]
      }
    ]
  }
}

Bentuknya lebih ramping: operatorName: "required" dengan specifiedAs.required berisi daftar field wajib versi skema, dan missingProperties berisi field yang benar-benar absen. Beda bentuk ini penting saat menulis penanganan galat programatik — kode yang selalu membaca propertiesNotSatisfied akan melewatkan kasus field yang hilang sama sekali.

Memperbaiki Data atau Memperbaiki Aturan #

Setelah penyebabnya terbaca, ada dua arah perbaikan dan keduanya sah tergantung siapa yang salah. Bila consideredValue memang data yang buruk (misalnya form mengirim umur: 11), perbaikannya di aplikasi: validasi input sebelum insert, atau perbaiki datanya lalu kirim ulang — nilai yang sudah benar akan lolos tanpa perubahan apa pun di database.

Bila yang keliru justru aturannya — misalnya bisnis kini menerima umur 10 tahun untuk akun anak — validator bisa diubah tanpa membangun ulang collection lewat collMod, dan selama masa transisi aturan bisa sementara dijalankan dalam mode warn (operasi berjalan, pelanggaran hanya dicatat). Kedua mekanisme itu dibahas penuh di Chapter Validation Actions and Validation Levels — satu-satunya aturan mutlaknya: jangan pernah menurunkan validasi hanya demi menembus satu data bermasalah.

Temuan di errInfoMaknaArah perbaikan
missingProperties terisiField wajib tidak dikirimLengkapi payload di sumber; cek pemetaan field aplikasi
bsonType gagalTipe salah (string vs int, dsb.)Konversi tipe di aplikasi sebelum insert
minLength / maximum / pattern gagalNilai di luar batas aturanPerbaiki nilai; atau tinjau ulang batasnya lewat collMod
Pelanggaran hanya di environment tertentuValidator berbeda antar environmentBandingkan db.getCollectionInfos() dev vs production

Rangkuman #

  • Kode 121 (DocumentValidationFailure) hanyalah pintu; errInfo-nya yang berisi pohon rincian lengkap.
  • Baca bertingkat: schemaRulesNotSatisfied → kategori → field → specifiedAs versus consideredValue.
  • Field wajib yang hilang tidak muncul di propertiesNotSatisfied — ia punya kategori required dengan missingProperties.
  • Dua arah perbaikan: data di aplikasi bila nilainya yang salah, aturan lewat collMod bila bisnisnya yang berubah.