Azure Static Web Apps に Next.js を GitHub Actions でデプロイすると、ビルドは通るのに最後だけ「Invalid API key」で落ちることがあります。トークン再生成やSecrets更新でも直らない場合に効く“作り直し”と、その後に出がちな「Web app warm up timed out」までまとめて解決します。
このトラブルが厄介な理由
「Invalid API key」は名前の通りトークンの間違いを疑うエラーですが、実際には GitHub Actions 側の設定が正しくても、Static Web Apps 側の初期構成が原因で失敗するケースがあります。特に次の条件に当てはまると、時間だけが溶けがちです。
- GitHub Actions のログ上は ビルド完了・成果物のアップロード完了まで進む
- 最後のデプロイ確定フェーズで
Deployment Failure Reason: Invalid API key AZURE_STATIC_WEB_APPS_API_TOKENは GitHub Secrets に入っている- トークン再生成、Secrets の更新、YAML の参照名確認をやっても改善しない
まずは切り分け:本当に「単純な設定ミス」ではないか確認
今回紹介する根本対処に進む前に、5分で終わる確認だけ済ませておくと安心です。ここで引っかかる場合は「作り直し」不要で直ることがあります。
| 確認ポイント | よくある落とし穴 | 確認方法 |
|---|---|---|
| Secrets の参照先 | リポジトリSecretsではなく Environment Secrets に入れていて参照できていない/逆もある | Workflow がどの Environment を使うか、Secrets のスコープが一致しているか確認 |
| Secret 名 | AZURE_STATIC_WEB_APPS_API_TOKEN の綴り違い(末尾のS、アンダースコア) | YAML で ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN }} になっているか |
| デプロイ先 | 別の Static Web App のトークンを入れている(環境が複数あると起きやすい) | Azure 側の対象リソース名と、トークン取得元が一致しているか |
| Workflow の action 指定 | action: "upload" が抜けていたり、古いテンプレが混ざっている | Azure/static-web-apps-deploy の例と比較 |
それでも解消しない場合、ここからが本題です。ポイントは「トークンそのもの」ではなく、Static Web Apps の作り方(初期の連携方式)にあります。
Invalid API key の根本原因:GitHub 連携で作った Static Web Apps が“トークン方式”と噛み合わない
結論から言うと、このパターンの「Invalid API key」は トークンが間違っている/期限切れというより、Static Web Apps の作成時に GitHub 連携(GitHub App 連携)で構成を作ったことが原因で、期待通りにトークンが通らない状態になっているケースがあります。
実際、次のような状況が同時に起きると、表面上は「トークン問題」に見えます。
- Azure Portal 側で GitHub 連携を選んで Static Web Apps を作成した
- その後、リポジトリ構成を変えた(monorepo化、ディレクトリ移動、別リポジトリへ移行など)
- Workflow を手で書き換えたり、Secrets を一般名(
AZURE_STATIC_WEB_APPS_API_TOKEN)に統一した - しかしデプロイ段階だけが通らない
このときの最短ルートは、原因探しを延々と続けるより 「Deployment token(デプロイトークン)方式」で Static Web Apps を作り直し、そこで生成された新しいトークンでデプロイすることです。
対処:Deployment token 方式で Static Web Apps を作り直す
手順はシンプルですが、“作成時の選択”が一番重要です。ポイントは「GitHub 連携」ではなく、デプロイトークンでデプロイする前提の構成で作ること。
作り直し手順(要点)
- Azure Portal で新規に Static Web Apps を作成する
- 作成時のデプロイソース(デプロイ方法)の選択で、GitHub 連携ではなく Deployment token(または Other / Manual deployment 相当)を選ぶ
- 作成後、Static Web Apps の「Deployment token」から トークンを取得する(必要なら再生成)
- GitHub リポジトリの Secrets に
AZURE_STATIC_WEB_APPS_API_TOKENとして登録する - Workflow の
azure_static_web_apps_api_tokenがその Secrets を参照していることを確認する
ここでの肝は「トークンを再生成する」ではなく、最初から“トークン方式の Static Web Apps”として作り直す点です。これで「Invalid API key」が解消することがあります。
作り直し時の移行チェック
作り直しは即効性がある一方で、運用中の環境だと移行ポイントを押さえておかないと手戻りします。最低限、次をチェックしてから切り替えると安全です。
| 移行項目 | 影響 | やること |
|---|---|---|
| 既存の公開URL | 既定ドメインは変わる | URLを固定したい場合はカスタムドメイン運用に寄せる |
| カスタムドメイン | 再設定が必要になることがある | DNS設定、証明書状態、ドメイン検証を事前に確認 |
| 認証(ログイン連携) | プロバイダ設定が紐づく | 利用している場合は設定内容を控えておき、新環境へ再設定 |
| アプリ設定(環境変数) | 静的エクスポートでは特に重要 | どの値がビルド時に必要かを整理し、GitHub Secrets/Variablesへ反映 |
| PRプレビュー環境 | 運用方法が変わる | プレビューが必要ならWorkflowとブランチ戦略も同時に見直す |
GitHub Actions 側の設定例(最小構成)
Workflow は最終的にこの形に寄せると安定します(Next.js のビルド方法は後述)。
name: Azure Static Web Apps CI/CD
on:
push:
branches:
- main
jobs:
build_and_deploy:
runs-on: ubuntu-latest
name: Build and Deploy
steps:
- uses: actions/checkout@v4
- name: Deploy
uses: Azure/static-web-apps-deploy@v1
with:
azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN }}
repo_token: ${{ secrets.GITHUB_TOKEN }}
action: "upload"
app_location: "/"
api_location: ""
output_location: "out"
※今回は「そこが原因ではない」ケースですが、一般的な確認として azure_static_web_apps_api_token が Secrets を正しく参照しているかは必ずチェックしてください。
Invalid API key 解消後に出やすい次の壁:Web app warm up timed out
「Invalid API key」が解消すると、次に以下へ移行することがあります。
Deployment Failure Reason: Web app warm up timed out
このエラーは、Static Web Apps がデプロイされたアプリを「起動確認(ウォームアップ)」しようとしたときに、期待した応答が返らずタイムアウトした状態を示します。Next.js では SSR(サーバーサイドレンダリング)前提の構成が混ざっていると発生しやすいです。
原因:Next.js が“静的サイトとして完結していない”
Static Web Apps は基本的に 静的ホスティングです。Next.js をそのまま載せると、プロジェクトの設定や機能の使い方によっては「実行時サーバーが必要なアプリ」になり、Static Web Apps の前提と衝突します。
特に、次の要素があると要注意です。
| 要素 | 何が起きるか | 結果 |
|---|---|---|
rewrites を Next.js 側で使用 | SSR/ランタイム相当の振る舞いを期待したルーティングになる | 静的エクスポートで成立せず、ウォームアップ失敗につながりやすい |
成果物が .next 前提 | Node サーバーで動かす前提のビルド成果物になりがち | Static Web Apps の「静的ファイル配信」とミスマッチ |
| 動的データ取得(SSR必須) | リクエストごとにサーバー処理が必要 | 静的ホスティングでは再現できない |
対処は、Static Web Apps に無理に合わせるなら 「静的として成立させる」ことです。
対処:Next.js を静的エクスポート向けに寄せる
ここからは「Static Web Apps で安定稼働させる」ための現実的な落とし所です。Next.js のすべての機能が使えるわけではありませんが、構成がハマると CI/CD は一気に安定します。
Next.js 設定:output: 'export' を追加し、rewrites をやめる
next.config.ts を静的エクスポート前提に変更します。最小構成は次の通りです。
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
output: "export",
// 画像最適化を使っている場合は静的エクスポートでは追加調整が必要になることがあります
// images: { unoptimized: true },
};
export default nextConfig;
重要:rewrites は削除(または少なくとも静的エクスポート前提の設計へ変更)します。Next.js の rewrites は「サーバーがルーティング処理をしてくれる」前提で組まれがちで、Static Web Apps の静的配信とは相性が悪いです。
Workflow の出力先:output_location を .next から out へ
静的エクスポートを有効にすると、デプロイすべき成果物は基本的に out 配下になります。GitHub Actions の設定もそれに合わせます。
| 項目 | SSR寄りの設定 | 静的エクスポート設定 |
|---|---|---|
| 出力フォルダ | .next | out |
Workflow の output_location | .next | out |
実際の Workflow では次のように指定します。
output_location: "out"
API 呼び出し:rewrites ではなく環境変数で“直接”呼ぶ
rewrites で「フロントは同一オリジンの /api を叩けば裏でバックエンドへ流れる」という作りにしていると、静的エクスポートへ寄せた瞬間に設計が崩れます。
そこで、フロント側は NEXT_PUBLIC_API_URL のような環境変数を使い、Azure App Service やコンテナ等のバックエンドへ 直接リクエストする形に変更します。
// 例:API クライアントのベースURLを環境変数から組み立てる
const baseUrl = process.env.NEXT_PUBLIC_API_URL;
export async function fetchUser() {
const res = await fetch(`${baseUrl}/users/me`, {
headers: { "Content-Type": "application/json" },
});
if (!res.ok) throw new Error("API request failed");
return res.json();
}
静的エクスポートで特に注意:Next.js の NEXT_PUBLIC_ 付き環境変数は “ビルド時に埋め込まれる” 性質があります。つまり、Azure Portal 側で後から値を変えても静的HTMLには反映されません。運用するなら次のどちらかに寄せると事故が減ります。
- GitHub Actions のビルド時に環境変数を渡して固定する(環境ごとにSecretsを分ける)
- 実行時に読み込む
config.jsonのようなファイルを用意し、フロントはそれを読んでURLを決める(静的でも差し替え可能)
Static Web Apps 側のルーティング設定で補う
Next.js の rewrites を外すと「SPA の直リンクで 404 になる」「ヘッダーやキャッシュを制御したい」など、別の困りごとが出ることがあります。その場合は、Static Web Apps のルーティング設定(staticwebapp.config.json)で補うのが現実的です。
例えば、クライアントサイドルーティングのある構成で直リンクを許可したい場合は、次のような設定が使われます。
{
"navigationFallback": {
"rewrite": "/index.html",
"exclude": ["/assets/*", "/favicon.ico"]
}
}
※ここでできるのは主に「配信側のルール制御」です。バックエンドへの“透過的なプロキシ”を Next.js の rewrites と同じ感覚で置き換えるのは難しいため、API は原則として直接呼ぶ(または別のゲートウェイを用意する)方が運用が安定します。
静的エクスポートでハマりがちなポイント
「設定を変えたらビルドが通らない/動かない」を防ぐために、静的エクスポートで制約になりやすい要素をまとめます。該当する機能がある場合は、早めに設計を切り替えるのが得策です。
| 機能・要素 | 静的エクスポートでの扱い | 回避・代替案 |
|---|---|---|
| SSR(リクエストごとに描画) | 基本的に不向き | SSG/ISR相当へ寄せる、またはSSR対応ホスティングへ移行 |
Next.js の rewrites | 期待通りに動かないことがある | APIは直接呼ぶ/必要なら別サービスでルーティング統合 |
API Routes(pages/api など) | 静的だけでは完結しない | Azure Functions や App Service に分離して運用 |
next/image の最適化 | サーバー機能が必要になりやすい | unoptimized 設定、外部画像CDN、事前最適化 |
| 環境変数の切り替え | ビルド時埋め込みで事故が起きやすい | ビルド時に注入する/実行時に読む設定ファイル方式 |
実務で効く:エラーから逆引きするチェックリスト
似たログでも原因が違うことがあるので、現場で使えるように “症状→当たりどころ” を表にまとめます。
| 症状(ログ) | 疑うポイント | 最短のアクション |
|---|---|---|
ビルド完了→アップロード完了→最後だけ Invalid API key | Static Web Apps の作成方法(GitHub連携の初期構成)が噛み合っていない | Deployment token 方式で新規作成→新トークンで Secrets 更新 |
Invalid API key が突然出る(以前は動いた) | トークンの再生成、Secrets の上書きミス、別環境のトークン混入 | トークン取得元を確認→Secrets を貼り直し→Workflow の参照名を再確認 |
Web app warm up timed out | Next.js が静的として成立していない(SSR、rewrites、出力先の不一致) | output: "export"、output_location: "out"、rewrites削除 |
| デプロイは成功するが画面が真っ白/404 | SPA ルーティング設定、ベースパス、静的ファイルの配置ミス | out に index.html があるか確認→staticwebapp.config.json を見直す |
Static Web Apps と Next.js を組み合わせるときの設計判断
最後に、同じところで迷う人が多い「Static Web Apps を使い続けるべきか」の判断軸を整理します。ここを最初に決めると、エラー対応が “その場しのぎ” になりません。
SSRを維持したいなら無理に Static Web Apps に寄せない
SSR(rewrites含む)を維持したいなら、Static Web Apps に無理に寄せるより、Next.js を自然に動かせるホスティング(Azure App Service、コンテナ、Vercel など)を検討した方がトラブルは減ります。Static Web Apps は “静的が主役” のサービスなので、SSR を前提にすると構成が複雑化しやすいです。
Static Web Apps を使うなら「静的として完結」か「バックエンド分離」
Static Web Apps を選ぶ場合は、次のどちらかに寄せるのが安全です。
- 静的として完結させる:CMS的な更新はビルドで反映、ページは SSG / 静的エクスポートで配信
- バックエンド分離で直接呼ぶ:フロントは静的、API は App Service / Functions / Container Apps など別サービスで運用
| 要件 | おすすめ | 理由 |
|---|---|---|
| SEO重視の静的サイト(更新頻度はそこまで高くない) | Static Web Apps + Next.js 静的エクスポート | 配信が速い、運用が軽い、GitHub Actions と相性が良い |
| ログイン後のダッシュボード中心(API 依存が強い) | Static Web Apps + バックエンド分離 | フロントは静的で十分、API は別でスケールさせやすい |
| SSR必須(リクエストごとに描画内容が変わる) | App Service / コンテナ / SSR対応ホスティング | Static Web Apps の前提と衝突しやすく、タイムアウト系トラブルが出やすい |
まとめ:今回の最短解は「トークン」ではなく「作成方式」と「静的成立」
「Invalid API key」は Secrets やトークン再生成で直ることもありますが、ビルド~アップロードまで成功して最後だけ落ちる場合は、Static Web Apps 側の初期構成が原因になっていることがあります。その場合は Deployment token 方式で作り直し、新トークンでデプロイが最短です。
さらに「Web app warm up timed out」に進んだら、Next.js の設定が SSR 寄りになっていないかを疑い、静的エクスポート(output: "export")と output_location: "out" を軸に構成を整えると安定します。Static Web Apps は “静的が主役” と割り切り、バックエンドは分離して設計するのが実務的に強い選択です。

コメント