同事象で苦しむ人は稀と思われるので、この記録が役に立つかは不明。
発端 #
- Serverless Framework にて AWS Lambda 上で動くコードを開発中。
- serverless-offline にて、ローカルで起動している Firebase Local Emulator の Cloud Firestore に以下のコードを実行するとエラーが発生。
(試してはいませんが、ローカル環境で上記が発生している場合、デプロイ後の本番の Lambda 上でも同様にエラーとなるはずです。)
import admin from "firebase-admin";
import serviceAccount from "***-firebase-adminsdk.json";
admin.initializeApp({
credential: admin.credential.cert(serviceAccount as admin.ServiceAccount),
});
const docData = {
stringExample: "Hello world!",
booleanExample: true,
numberExample: 3.14159265,
dateExample: admin.firestore.FieldValue.serverTimestamp(),
arrayExample: [5, true, "hello"],
nullExample: null,
objectExample: {
a: 5,
b: {
nested: "foo",
},
},
};
db.collection("data").doc("one").set(docData);
エラーメッセージは以下
Request message serialization failure: util.Long.fromValue is not a function
送っているパラメータを一つずつ確認していくと、どうやら以下の3つを送ろうとすると上記エラーになる。タイムスタンプと配列とマップがダメな様子。
- dateExample
- arrayExample
- objectExample
原因 #
いろいろ調べてみると下記が原因だった。(参考にしたソースは本記事の最後にまとめます。)
- node モジュールの
firebase-adminの依存先を辿っていくと、依存パッケージの一つにlongがある。バージョンは 4.0.0 以上が指定されている。 serverlessの依存先を辿っていくと、これも依存パッケージの一つにlongがある。バージョンは 1.1.2 が指定されている。- 古いバージョンの
long(< 2.1.0)にはfromValue methodが存在しない。 package.lock.jsonで最終的に指定されているlongを見ると以下になっていた。
"long": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/long/-/long-1.1.2.tgz",
"integrity": "sha1-6u9ZUcp1UdlpJrgtokLbnWso+1M=",
"dev": true
},
ご覧の通り 1.1.2 の方が適用されている。
理由 #
- 古いバージョンと新しいバージョンの
longどちらが最終的に適用されるかは、package-lock.json内で読み込む順番によって決まり、先に読み込んだ方が適用される。 - 私の場合、
package-lock.jsonではserverlessの方がfirebase-adminよりも先に記載されており、そのため 1.1.2 のlongが最終的に適用されていた。
解決策 #
- 新しいバージョンの
longを適用させる必要がある。 - そのためには、
firebase-adminをserverlessよりも先に記載すれば良い。 package-lock.jsonへ記載される順番は、npm installした順番によって決まるため、まずはnpm i firebase-adminその後npm i serverlessすれば良い。
なお、 package.json では dependencies に firebase-admin を、 devDependencies に serverless を 指定しているのが通常と思われるが、その状態であれば、一度 package-lock.json を削除した後 npm install すれば firebase-admin の方が上位に記載されているはず。
原因振り返り #
私の場合は、まず npm install --save-dev serverless し、その後 npm install firebase-admin していたため、本事象が発生する状態となっていた。
解決後の状態 #
package-lock.json を確認すると、 long のバージョンが 4.0.0 になっていることが確認できた。firebase-admin を利用したコードも問題なく動いた。
"long": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz",
"integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA=="
},