【Node.js】【MongoDB】connection destroyed, not possible to instantiate cursorの原因と対処法

Node.jsからMongoDBに繋いだときのエラーメッセージ「MongoNetworkError: connection destroyed, not possible to instantiate cursor(接続が破壊されました。カーソルをインスタンス化することはできません)」の対処法です。

英語記事しかなく原因特定に時間がかかりましたので、日本語で解説してみました。

Webからのエラー画面

エラーの原因の特定と対処法

エラーとなっているのはNode.jsのmongodbライブラリ

ログを参照するとエラーを出力しているのはNode.jsのmongodbライブラリです。

MongoDBを直接検索してみても同じエラーは発生していません。

エラーが発生している箇所の検索処理を確認する必要があります。

MongoNetworkError: connection destroyed, not possible to instantiate cursor
    at nextFunction (/home/kenne/hammerhead/node_modules/mongodb-core/lib/cursor.js:645:9)
    at Cursor.next (/home/kenne/hammerhead/node_modules/mongodb-core/lib/cursor.js:833:3)
    at Cursor._next (/home/kenne/hammerhead/node_modules/mongodb/lib/cursor.js:211:36)
    …

発生条件は100件以上の検索

発生条件は100件以上の検索です。
厳密に100件ではく90件程度でも発生する場合もあります。

いつもより検索結果が多くなっていればそれが発生条件となります。

原因はdb.close()の位置

検索条件が一箇所の場合、原因はdb.close()の位置を確認してください。
dbo.collection〜.toArray()のネスト外にある場合、結果が返る前にdb.close()が実行されてしまうため、ネスト内に記述を移動する必要があります。

なお、検索結果の件数が発生条件になっており、db.close()の位置がネストの外にあっても検索結果が少なければエラーは発生しません

以下のようにdb.close()をネスト内に記載します。

let executionResult = {};
dbo.collection("execution").find().toArray(function(err, res) {
  if (err) throw err;
  executionResult = res;
  // ここが正しい位置
  db.close();
});
// ここに記載しているとエラーとなる。
// db.close();

二箇所以上の検索を行なっている場合

二箇所以外の検索の場合はdb.close()がネスト内になっていてもエラーが発生します。

二箇所以上の検索の場合は、検索結果が少ない方のdb.close()が先に処理されてしまいエラーが発生します。

setTimeout()を設定することでエラーを回避することができます。

let executionResult = {};
let statusResult = {};
dbo.collection("execution").find().toArray(function(err, res) {
  if (err) throw err;
  executionResult = res;
  setTimeout(function(){
    db.close();
  },50)
});
dbo.collection("status").find().toArray(function(err, res) {
  if (err) throw err;
  statusResult = res;
  setTimeout(function(){
    db.close();
  },50)
});


JavaScriptをマスターして一歩先のエンジニアに。

JavaScript 第6版

JavaScript 第6版