Vercel で 502 OPTIMIZED_EXTERNAL_IMAGE_REQUEST_UNAUTHORIZED Error に遭遇する。
前提
- Next.js を利用したアプリケーションを vercel へデプロイして利用している。
- 一部 item 詳細ページでは SSG を使っていて、一覧ページでは逐次別でホスティングしている API へリクエストを送る。
- 取得した item ごとに画像が紐付いていて、画像は cloudfront でホスティングされている。
- 画像の表示には next/image Image を利用している。したがって next.js の API 機能によって最適化がされている状態。
発生したこと
- ローカル環境での dev では問題なく画像が表示されていて、そのまま vercel 上へ build & depoly した。deploy までは特にエラー無く実行できた。
- 変更へ紐づくURLを preview でみてみると、殆どの画像が
502 OPTIMIZED_EXTERNAL_IMAGE_REQUEST_UNAUTHORIZED
エラーになり表示できていないことがわかった。
対応した (が上手く行かなかった) こと
- そもそも設定が間違っている可能性を考えてローカル環境で vercel がやっている(であろう)ことと同じ構成を試す。
- Web上で同じエラーメッセージで検索しても何も出てこない。vercel 公式のエラー一覧 https://vercel.com/docs/errors にもこのエラーコードがない (どういうこと?)
ここまでで困って twitter でつぶやいていたところ vercel の @jrsyo さんに tweet を見つけていただき DM で対応してもらいました。
vercelさんとても使い勝手よいのできにいった! のだけど画像の最適化が上手く行かなくて困っている… 手元でbuild & startしたときは問題なく _next/images/ へアクセスできるのにデプロイすると502 OPTIMIZED_EXTERNAL_IMAGE_REQUEST_UNAUTHORIZED エラーになる。
— nyker_goto (@nyker_goto) 2023年3月9日
DM で詳細もらえれば見てみますー!
— Shohei Maeda (@jrsyo) 2023年3月9日
(やさC)
結論何が問題だったか
画像の cloudfront にアクセス制限がかかっており local = ja のみアクセス可能になっていたことが問題でした。terraform の設定的に言うと、以下のような記載をしていました。
restrictions { # 日本以外は許可しない設定 geo_restriction { restriction_type = "whitelist" locations = ["JP"] }
ローカル環境は日本なので、問題なくアクセスできます。ただし vercel のエンドポイントは日本以外のどこかに立っています (確かアメリカのハズ)。
したがって、ある画像@cloudfront をフロントエンドから vercel の画像最適化用のエンドポイント _next/image
へリクエストすると, vercel → cloudfront へリクエストが飛びますが, vercel は日本にはないためアクセスが遮断され, vercel → cloudfront のリクエストが 403 error になり、結果フロントエンドには 502 OPTIMIZED_EXTERNAL_IMAGE_REQUEST_UNAUTHORIZED
が帰る、ということでした。
日本から利用することをメインに想定するアプリを作ることが多く上記設定をテンプレートに入れていたのですが、それを忘れていたことが原因なのですが cloudfront を疑うパターンが少なかったのでハマってしまいました。
余談
vercel の管理画面やエラー詳細ではそのような表示は見つけられなかった (ゆえに cloudfront の設定を疑っていなかった…) ので、エラーの細かいものを見る画面はないですかー? と @jrsyo さんに聞いたところ、今現在は提供されていないとのことでした。エラーの中身が見えるようになると嬉しいな🦈( ‘-’ 🦈)。vercel の追加開発に期待です。