cloud functionsのエラー「Error: Process exited with code 16」を防ぐには?


はじめに

元ネタはこちら

ある日、cloud functionsで新しい関数をデプロイしました。
すると、しっかり動作確認はできていたのに大量のエラーが発生しました。。

Error: Process exited with code 16
    at process.on.code (/layers/google.nodejs.functions-framework/functions-framework/node_modules/@google-cloud/functions-framework/build/src/invoker.js:275:22)
    at process.emit (events.js:198:13)
    at process.EventEmitter.emit (domain.js:448:20)
    at process.exit (internal/process/per_thread.js:168:15)
    at Object.sendCrashResponse (/layers/google.nodejs.functions-framework/functions-framework/node_modules/@google-cloud/functions-framework/build/src/logger.js:37:9)
    at process.on.err (/layers/google.nodejs.functions-framework/functions-framework/node_modules/@google-cloud/functions-framework/build/src/invoker.js:271:22)
    at process.emit (events.js:198:13)
    at process.EventEmitter.emit (domain.js:448:20)
    at emitPromiseRejectionWarnings (internal/process/promises.js:140:18)
    at process._tickCallback (internal/process/next_tick.js:69:34) 

このエラーはそもそも何?

結論から言うと、わかりません!!
だって検索しても何も情報がないんだもん。。。

このエラーを防ぐには?

下記のコードは僕が実際にアプリで使っているものです。

userがeventを作成(というかonWriteトリガーなので、作成、削除、更新のいずれか)したときに発動する関数で、作成したeventの数をカウントしています。
詳しくはこちら
Firebase 要素の数をカウントするなら、最初からこの方法でいきましょう!(Cloud Functions)

exports.monthCountEvents = functions.region('asia-northeast1').firestore
  .document('users/{userId}/events/{eventId}')
  .onWrite((change, context) => {

    let pushMonths: any;
    let periods: boolean;
    let dayEventCounts: number;
    if (!change.before.exists) {
      pushMonths = change.after.get('pushMonths');
      periods = change.after.get('periods');
      dayEventCounts = change.after.get('dayEventCounts');
    } else {
      pushMonths = change.before.get('pushMonths');
      periods = change.before.get('periods');
      dayEventCounts = change.before.get('dayEventCounts');
    }

    const userId = context.params.userId;
    const FieldValue = admin.firestore.FieldValue;
    const monthCountRef = db.collection(`users/${userId}/counts`).doc(pushMonths);
    monthCountRef.get().then((docSnapshot) => {
      if (!docSnapshot.exists) {
        monthCountRef.set({ monthCount: dayEventCounts, monthDate: pushMonths });
      } else {
        if (!change.before.exists && !periods) {
          // 登録時に件数をインクリメント
          monthCountRef.update({ monthCount: FieldValue.increment(dayEventCounts) });
        } else if (change.before.exists && !change.after.exists && !periods) {
          // 削除時に件数をデクリメント
         monthCountRef.update({ monthCount: FieldValue.increment(-dayEventCounts) });
        }
        return;
      }
    // catchが重要らしい!
    }).catch((error) => {
      console.log("monthCountRef Error getting document:", error);
    });
  });

とりあえず.catchを使うことでこの手のエラーは回避できるようです。

.catch((error) => {
      console.log("monthCountRef Error getting document:", error);
    });

謎な点は「エラーでまくってても、時間が経てば正常に処理されている」と言う点だろうか・・・

最初「やべー、本番環境やのにエラーでまくってる〜!!!」と焦ってたのですが、、
次の日Firestoreを見ると、エラーで実行されなかったと思われていた処理が、なんと普通に実行されていたのです。。。

つまり、cloud functionsのonWriteトリガーで、「A」と言うdocumentを作成する処理があったとして、その処理はError: Process exited with code 16でストップしたと思っていました。

しかし時間が経ってから見ると、「A」と言うdocumentは作成されていました。

うーん、よくわからんけどすごいぞFirebase!!!