firebase deploy --
only functions:### がエラーになりFunctionsをデプロイできない
結論:node.js・Firebase CLI・TypeScriptを更新、try catch文に型判定を導入
2022/11/14 Flutter エラー・バグ日記
画像認識ができるCloud Vision APIにアクセスするため、FunctionsのサンプルコードをFirebaseにデプロイすべく、
firebase deploy --only functions:(関数名)
を実行したら、下記のような膨大なエラーが発生。。
以前、整理したCloud Vision APIの使用方法(下記記事ご参照)に沿って、久しぶりに実行したのだが、うまく行かない。
結局、色々なことを試し、解決するのにかなり苦労した。。
本日記では、解決につながった方法のみ、履歴として残しておく。
先に結論をまとめておくと、必要だった対応は以下の通り。
- node.jsを更新する(16.10.0 または 18.0.0以上にする)
- Firebase CLIを最新に更新する(9.17.0 以降にする)
- npm install typescript@latest をする(最新に更新する)
- index.ts の try catch 文を修正する(引数の型判定を行う)
使用したFunctionsのサンプルコード
Google公式の下記GitHubに公開されている、画像認識用のコードを「git clone」して使用。
ちょうど4日ほど前(2022/11/10頃)に更新されたばかりの模様。
①node.jsのバージョンを「16.10.0」に更新
エラーの内容を見ると、TypeScriptで書かれているファイル(.tsファイル)に「,」や「]」が無い、といった文法系のエラーが出ている模様。
TypeScriptについては理解が乏しいが、バージョン差異による問題と思われたので、パッケージのイントールに用いるnode.jsのバージョンを更新(同時にnpmのバージョンも更新される)することにした。
本日記時点で、node.jsの最新バージョン(推奨版)は、「18.12.1」。
しかし、サンプルコードの「functions/package.json」ファイル内で、
"node": "16"
が指定されていること、
また、functionsフォルダ内で、「npm install」をした際に、
npm WARN EBADENGINE required: { node: '^14.15.0 || ^16.10.0 || >=18.0.0' }
の警告が出たこと、
を受け、「sudo n 16.10.0」のコマンドで、「16.10.0」に更新した。
※バージョンを指定してのインストールは、公式サイトからのインストーラーではできないようなので、まず「npm install -g n」でnode.jsのパッケージ管理ツール「n」をインストールし、「n」コマンドを使用できるようにした。
こちらの記事に大変助けていただいた(ありがとうございます!)。
②Firebase CLIを最新に更新
Cloud Functionsの下記公式説明
によると、node.js 16を使うには、Firebase CLIのバージョン「9.17.0」 以降を使用する必要があると書かれていた。
自分の使っていたバージョンを調べると、「9.16.0」でギリギリ未達。。。
※この要件を見落としていたので、バージョン関係の別のエラーも発生していて、解決に時間がかかってしまった。。
更新の方法は、下記公式サイト
に説明があるが、どうやっても「npm install -g firebase-tools」を使って更新するとエラーになるので、自動インストールスクリプト(下記コマンド)で更新した(現時点では「11.16.0」が最新)。
curl -sL https://firebase.tools | upgrade=true bash
※こちらのイシューによると、Firebase関連は「npm」だとうまく行かない事が多い模様。。
③TypeScriptのバージョンを最新に更新
node.jsとFirebase CLIを更新しただけでは、エラーは解消しないので、エラーメッセージでググると、類似した内容の下記記事が見つかった。
回答によると、「typescript」のバージョンを最新に更新すると良いとのこと。
サンプルコードの「functions/package.json」を見ると、「"typescript": "^3.8.0"
」になっている。
そこで、記事内の情報どおり
npm install typescript@latest
を実行すると、「functions/package.json」の記載が、「"typescript": "^4.8.4"
」に更新された。
この状態でデプロイしたところ、エラーメッセージが大幅に減り、以下のエラーのみになった。
############## % firebase deploy --only functions:annotateImage === Deploying to 'YYYYYYYYYY'... i deploying functions Running command: npm --prefix "$RESOURCE_DIR" run build > functions@ build XXXXXXXXXXXXXXX /functions-samples/vision-annotate-images/functions > tsc src/index.ts:25:54 - error TS2571: Object is of type 'unknown'. 25 throw new functions.https.HttpsError("internal", e.message, e.details); src/index.ts:25:65 - error TS2571: Object is of type 'unknown'. 25 throw new functions.https.HttpsError("internal", e.message, e.details); Found 2 errors in the same file, starting at: src/index.ts:25
ターミナルの画面上では、「e.message」と「e.details」の各「e.」の下に、エラーを示す赤い波線が出ていた。
④try catchの引数を「instanceof」で型判定するように修正
どうやら画像認識の関数を呼び出すサンプルコード「functions/src/index.ts」内の「try catch」文(エラーハンドリング)の文法に問題があるらしい。
調べると、関連しそうな下記記事が見つかった。
また、こちらのTypeScript公式のページ
を見ると、TypeScriptのバージョン4.0.0以降は、例外処理で渡される引数(上記では「e」)の型に応じて、処理を分ける必要があるらしい。
結果、以下のように「index.ts」を修正することとした。
↓index.tsの一部抜粋
export const annotateImage = functions.https.onCall(async (data, context) => { if (!context.auth) { throw new functions.https.HttpsError( "unauthenticated", "annotateImage must be called while authenticated." ); } try { return await client.annotateImage(JSON.parse(data)); } catch (e) { // ↓元のコード // throw new functions.https.HttpsError("internal", e.message, e.details); // ↓以下の内容に差し替え // 修正箇所 ここから if (e instanceof Error) { // Error型であることを確認したらエラーメッセージを投げる。e.detailsはエラーになるので削除 throw new functions.https.HttpsError("internal", e.message); } else { // Error型でなかった場合も何らかthrowを書かないとエラーになる throw console.log("other issues"); } // 修正箇所 ここまで } });
else以下の部分を省略すると、下記のようなエラーになるので、仕方なくelseの場合は、console.logを表示するthrowを追加した。
以上で再度デプロイしたら、やっとのことで成功した!
(補足1)コンパイルオプションを修正
後で気づいたが、こちらの記事に説明があるとおり、TypeScriptのコンパイルオプション(compilerOptions)を「"strict": false
」に設定すれば、try catch部分のエラーは発生しないとのこと。
確かに、サンプルコードの「functions/tsconfig.json」にあるTypeScriptのコンパイルオプション(compilerOptions)は「"strict": true
」になっていた。
実際、これを「"strict": false
」に修正してデプロイしたところ、エラーを回避できた。
そのため、「index.ts」を修正したくない場合は、この方法も有効だと思われる(チェックが緩いコンパイルになる、ということだと思うので、若干不安ではあるが、、)。
(補足2)firebase-functionsとfirebase-adminを更新(未検証)
見落としていたが、、Cloud Functionsの下記公式ページ
を見ると、以下のような記述があった。
多くの場合、新しい機能とバグ修正は、最新バージョンの Firebase CLI とfirebase-functions SDK でのみ利用できます。 Firebase プロジェクトのfunctionsフォルダー内で次のコマンドを使用して、Firebase CLI と SDK の両方を頻繁に更新することをお勧めします。
npm install firebase-functions@latest firebase-admin@latest --save
npm install -g firebase-tools
(出典)https://firebase.google.com/docs/functions/get-started
別の影響が出ると困るので、試せていないが、「firebase-functions」の更新については、デプロイ完了時の警告メッセージにも出ていたので、もしかすると1行目のコマンドを実行しておけば、エラーは回避できたのかもしれない。。(なお、2行目のコマンドは、前述のとおり、curlコマンドで実施済)
(2022.12.17追記)
その後、
npm install firebase-functions@latest firebase-admin@latest --save
を試してみたが、結局これだけではエラーは解消しなかった。
そのため、やはり前述の①〜④の対処が必要、というのが現時点での結論。。
Firebase CLIやnpm絡みでは、毎回バージョン関係のエラーで苦労する。。
\一般的なエラー対処法をまとめた記事はこちら/
リリースしたアプリ(全てFlutterで開発)
個人アプリ開発で役立ったもの
おすすめの学習教材
\超初心者向けでオススメな元Udemyの講座/
\キャンペーン時を狙えば安価で網羅的な内容が学べる(日本語訳あり)/
\Gitの基礎について無料で学べる/
おすすめの学習書籍
\実用的。image_pickerに関してかなり助けられた/
\Dartの基礎文法を素早くインプットできる/