ある夜、運用中のアプリのバックエンドを Cloudflare Workers に移したあと、Gemini API への問い合わせがすべて 400 INVALID_ARGUMENT: User location is not supported for the API use で落ち始めました。ローカルの Mac では同じコードが普通に動きます。デプロイした Worker からだけ全滅です。
ローカルとサーバーで同じコードが動かないとき、開発者の心が一番すり減る瞬間だと感じています。私自身、2014年から個人でアプリを出し続けてきて累計5,000万ダウンロードほどになりますが、こうした「環境差の沼」は何度経験してもしんどいものです。今回はその夜に試した順番を、実用的な切り分け表として残します。
このエラーが出る本当の理由
User location is not supported for the API use は、Gemini API が リクエスト元の IP アドレスを地理的にサポート対象外と判定したとき に返ります。api.generativelanguage.googleapis.com(いわゆる Gemini Developer API)は、利用可能な国・地域が公式ドキュメントで明記されており、対象外のリージョンから接続すると 400 で弾かれます。
ここで詰まるのは「日本からのアクセスはサポートされているはずなのに、なぜ落ちるのか?」という点です。原因はほぼ次のどれかに集約されます。
- Cloudflare Workers の出口 IP が、Google から見たときに非対応リージョンに見えている
- Vercel Edge Functions / Netlify Edge Functions が、リクエスト処理を別リージョンの PoP に振った
- VPN / プロキシ経由でアクセスしていて、出口 IP が想定外
- Google Cloud のサービスアカウント請求先プロジェクトのリージョン設定(Vertex AI 経由の場合)
切り分けに必要なのは「自分のリクエストが Google から見てどの国から来ているか」を確認する作業です。
順番1: 出口 IP を可視化する(最初の30秒)
最初にやるべきは、サーバーから外向きの IP がどこのリージョンと判定されているかを確認することです。私はだいたい次のような小さなエンドポイントを Worker に仕込んで確かめます。
// Cloudflare Worker で出口IPの判定リージョンを確認
export default {
async fetch(req: Request): Promise<Response> {
// 第三者サービスを使って、自分のWorkerが「どこから来た」と見られるかを取得
const res = await fetch("https://ipinfo.io/json");
const data = await res.json();
return new Response(JSON.stringify(data, null, 2), {
headers: { "content-type": "application/json" },
});
},
};
// 期待する出力例:
// {
// "ip": "104.16.xxx.xxx",
// "city": "...",
// "country": "...",
// "org": "AS13335 Cloudflare, Inc."
// }ここで country が「JP」以外、たとえば US や SG になっていたら、それが直接の原因です。Cloudflare Workers は世界各地の Edge から実行されるため、ユーザーが日本から叩いても、Worker 自身が出ていく IP は別の国のデータセンターになることがよくあります。
順番2: Vertex AI 経由に切り替える(最も確実)
公式が推奨するもっとも確実な解決策は、Gemini Developer API(generativelanguage.googleapis.com)から Vertex AI(aiplatform.googleapis.com)への切り替え です。Vertex AI は Google Cloud のリージョンを明示的に指定でき、asia-northeast1(東京)や asia-northeast2(大阪)を選べます。エッジから呼んでも、宛先側のリージョンが固定されるので「出口 IP がどこか」に左右されにくくなります。
# Vertex AI クライアントで東京リージョンを明示
from google import genai
client = genai.Client(
vertexai=True,
project="your-gcp-project-id",
location="asia-northeast1", # ← 重要: 日本リージョンを明示
)
response = client.models.generate_content(
model="gemini-2.5-flash",
contents="個人開発者向けに、Vertex AI 移行の手順を3行で要約してください。",
)
print(response.text)
# 期待出力(要約例):
# 1. GCPプロジェクトを作成しサービスアカウントを発行する
# 2. Vertex AI APIを有効化し ADC を設定する
# 3. genai.Client(vertexai=True, location="asia-northeast1") に切り替えるここで一段ハードルになるのが認証です。Vertex AI は API キーではなく Application Default Credentials(ADC)を要求します。サービスアカウントの権限設定で詰まる方はVertex AI + Gemini 認証エラーの解決方法が補助線になります。
順番3: エッジではなく特定リージョンの Origin から呼ぶ
Vertex AI への移行が時間的に難しい場合、Gemini API を叩く処理だけを、確実に日本からアクセスできる Origin(リージョン固定のサーバー)に逃がす のが現実的です。私が小規模アプリで実際にやったパターンは次の3つです。
- Cloud Run(asia-northeast1)にプロキシを立てる: Worker は受け付け役、実際の API 呼び出しは Cloud Run に委譲
- Vercel の Functions を
Node.js Runtimeに変える: Edge Runtime ではなくサーバーレス関数として日本ノードで動かす - Fly.io の
nrt(東京)リージョンに小さな Node サーバーを立てる: 1ヶ月数百円〜で運用可能
判断基準は「リクエスト頻度 × レイテンシ要件」です。秒間で叩くリアルタイム用途でないなら、Cloud Run / Fly.io の組み合わせで十分回ります。
順番4: 同一エラーでも別の原因のケース
ときどき、IP リージョンが日本になっているのに同じエラーが返るケースに遭遇します。これは見落としやすいのですが、Gemini API のキーを発行した Google アカウント自体の地域設定 が古いまま、対象外リージョンの請求アドレスに紐付いているパターンです。
確認する場所は次の通りです。
- Google AI Studio のアカウント設定で表示される国
- Google Cloud 請求アカウントの請求先住所(Vertex AI を使う場合)
- 既に作成済みの API キーが、サポート外リージョンで発行されたもの
該当する場合は 新しい API キーを再発行する のが一番早く済みます。私の経験では、古いアカウントの請求情報が引きずられているケースで、3時間かけて切り分けるより、新キー発行のほうが明確に早く解決しました。
順番5: それでも消えないときの最終手段
ここまでで解決しなければ、SDK バージョンと利用モデルの組み合わせ を疑います。Gemini 3 系の一部プレビューモデルは、特定リージョンからの呼び出しが制限されることがあります。
# SDKのバージョンを確認し、最新化
pip show google-generativeai
pip install --upgrade google-generativeai
# モデルを安定版(gemini-2.5-flash / gemini-2.5-pro)に一旦下げて確認
# 期待: 安定版で通るなら、プレビューモデルのリージョン制限が原因私はこの順番で再現性のある復旧手順をたどっています。直す目的は「アプリを動かし続けること」であって「最先端モデルを使い続けること」ではないと割り切ると、判断が速くなります。
まずやるべき次のアクション
もし今このエラーで詰まっているなら、まず順番1の「出口 IP の可視化」を5分だけ試してみてください。country が日本以外になっていれば、迷わず Vertex AI への移行を選んだほうが、長期的に安定した本番環境が手に入ります。関連して認証で詰まったらGemini API vs Vertex AI 比較ガイドも移行判断の助けになります。
私自身、長年アプリを個人で動かし続けてきた経験のなかで、この種の「環境差で落ちるエラー」は何度も繰り返してきました。同じ夜に同じ画面と向き合っている方が、少しでも早く眠れる手助けになれば嬉しいです。お読みいただきありがとうございました。