こんにちは、 @dz_ こと大平かづみです。
Prologue - はじめに
Azure Functions で、Node.js で書いたコードを再び動かしたところ、以下のエラーで動かなくなってしまいました。
ファンクションの実行自体は終わってるようなのに、 mscorlib: Buffer cannot be null. Parameter name: buffer.
という見慣れないエラーが発生しています。
途方に暮れていましたが、原因と解決方法がわかったので記録します。
エラー内容
2017-02-08T10:30:00.005 Function started (Id=ebc259da-f172-4c93-a58f-f83605cd1df8)
2017-02-08T10:30:27.857 Function completed (Failure, Id=ebc259da-f172-4c93-a58f-f83605cd1df8)
2017-02-08T10:30:27.857 Exception while executing function: Functions.TimerTriggerJS1. mscorlib: Buffer cannot be null.
Parameter name: buffer.
発生環境
- Azure Functions
- Node.js
- Storage BLOB の出力バインド
関数の処理は、データベースから読み出した JSON データを Azure Blob Storage に保存するものです。
調査結果
この mscorlib: Buffer cannot be null. Parameter name: buffer.
は、どうやら .NET Framework の環境で発生する汎用的なエラーメッセージのようで、なかなか原因を特定できませんでした。
しかし、ファンクションの処理自体は終わっていることに着目すると、どうやら Node.js の処理ではなく、 Azure Functions 側で起こってるようです。
- 参考: Scripting the Azure WebJobs SDK: Runtime of Azure Functions, a light-weight scripting model for Azure WebJobs SDK.
- 参考: Azure WebJobs SDK
ファンクション実行完了後に処理されるのは… 私が設定していた「出力バインド」。
これだ!
結論
私の処理では、Storage BLOB の出力バインドに JSONオブジェクト を渡していました。
Azure Functions は、Storage BLOB にオブジェクトを出力すると、シリアル化してテキストファイルとして保存してくれます。
どうやら、渡した JSONデータが膨大すぎて、シリアル化でコケていたようです。
module.exports = function(context) {
// 出力する JSONデータを取得する
var jsonData = getJsonData();
// ★ BLOB 出力バインドに渡す (※だがしかし、オブジェクトが大きすぎた)
context.bindings.myOutputBlob = jsonData;
context.done();
};
そこで試しに、先に JSON.stringify()
で文字列化してから渡してあげると、無事出力されるようになりましたとさ♪
module.exports = function(context) {
// 出力する JSONデータを取得する
var jsonData = getJsonData();
// ★ 文字列型に変換してから、 BLOB 出力バインドに渡す
context.bindings.myOutputBlob = JSON.stringify(jsonData);
context.done();
};
ちなみに、当初はデータの少ない状態だったため発生しなかったが、しばらくしてデータが増えた後に実行したことにより発覚ということでした。(実運用前でよかったw)
めでたしめでたし (。・ω・)ノ
Epilogue - おわりに
このエラー、わかってしまえば簡単なことだったんですが、数日悩んでました。無事解決してほっとしてます。
今回は、BLOB でしたが、別の出力でも同様の状況がありそうです。プラットフォームやフレームワーク側に負担をかけない処理を心がけねばなりませんね!