Antigravity を使って Gemini API の Python コードを書いていると、動作確認の段階で「なんか変なエラーが返ってくる」という経験をされる方が多いのではないでしょうか。
エラーメッセージが英語だったり、HTTP ステータスコードだけだったりすると、何が原因なのかパッとわからなくて時間を消耗してしまいます。私自身も最初は RESOURCE_EXHAUSTED というエラーに出会ったとき、「リソースが枯渇? メモリ? CPU?」と見当違いの方向に調べて30分無駄にしました。
エラーメッセージのどの部分を見ればいいか、どう修正すればいいかが分かるようになることを目指しています。
まず:エラーの種類を正確に把握する
Gemini API のエラーは google.api_core.exceptions モジュールの例外として返ってきます。except Exception as e で丸ごと捕まえるのではなく、エラーの種別ごとに分けて処理するのが診断の第一歩です。
import google.generativeai as genai
from google.api_core import exceptions as google_exceptions
genai.configure(api_key="YOUR_GEMINI_API_KEY")
model = genai.GenerativeModel("gemini-2.5-flash")
try:
response = model.generate_content("こんにちは")
print(response.text)
except google_exceptions.ResourceExhausted as e:
print(f"クォータ超過: {e}")
except google_exceptions.InvalidArgument as e:
print(f"リクエスト形式エラー: {e}")
except google_exceptions.DeadlineExceeded as e:
print(f"タイムアウト: {e}")
except google_exceptions.PermissionDenied as e:
print(f"認証エラー: {e}")
except Exception as e:
print(f"その他のエラー: {type(e).__name__}: {e}")except のブロックでエラーの型を確認できると、「何が起きたか」が一目瞭然になります。以降のセクションでは、それぞれのエラーを個別に掘り下げます。
RESOURCE_EXHAUSTED (429) — クォータ超過エラー
エラーメッセージに RESOURCE_EXHAUSTED または HTTP 429 が出た場合、API の利用上限(クォータ)に達しています。
Gemini API の無料枠には「1分あたりのリクエスト数(RPM)」と「1日あたりのトークン数(TPD)」の2種類の制限があります。開発中にループでテストしているとすぐに RPM 制限に引っかかります。
よくある原因として多いのは、for ループの中で generate_content() を連続呼び出ししているケース、再帰的なエージェント処理でリクエストが爆発的に増えているケース、複数のスクリプトを並行実行しているケースなどです。
指数バックオフ(Exponential Backoff)でリトライを実装すると、一時的なクォータ超過に対して堅牢になります。
import time
import random
import google.generativeai as genai
from google.api_core import exceptions as google_exceptions
def generate_with_retry(model, prompt, max_retries=5):
"""指数バックオフ付きの generate_content"""
for attempt in range(max_retries):
try:
return model.generate_content(prompt)
except google_exceptions.ResourceExhausted as e:
if attempt == max_retries - 1:
raise # 最終試行でも失敗したら例外を投げる
wait_time = (2 ** attempt) + random.uniform(0, 1)
print(f"クォータ超過。{wait_time:.1f}秒後にリトライ ({attempt + 1}/{max_retries})")
time.sleep(wait_time)
model = genai.GenerativeModel("gemini-2.5-flash")
response = generate_with_retry(model, "テスト")
print(response.text)長期的な対策としては、Google AI Studio でクォータの現在値を確認し、必要であれば有料プランへの移行を検討するのが良いでしょう。
INVALID_ARGUMENT (400) — リクエスト形式エラー
INVALID_ARGUMENT は「送ったリクエストの形式が間違っている」というエラーです。HTTP 400 です。
このエラーが厄介なのは、原因が複数あるからです。私が実際に踏んだケースを中心にまとめます。
パターン1: マルチモーダルのファイル形式が不正
画像や PDF を渡す際、ファイルの読み込み方が間違っているとこのエラーが出ます。
# ❌ こうするとエラー(バイト列をそのまま渡している)
with open("image.jpg", "rb") as f:
image_bytes = f.read()
response = model.generate_content(["この画像は何ですか?", image_bytes])
# → INVALID_ARGUMENT: Request contains an invalid argument.
# ✅ 正しい書き方(PIL を使う)
import PIL.Image
image = PIL.Image.open("image.jpg")
response = model.generate_content(["この画像は何ですか?", image])
print(response.text)パターン2: コンテキストウィンドウのオーバー
一度に渡すテキストが長すぎる場合も INVALID_ARGUMENT になることがあります。エラーメッセージに token_count や max_tokens が含まれていたらこのケースです。
テキストを分割して渡すか、gemini-2.5-pro のように大きなコンテキストウィンドウを持つモデルに切り替えると解決します。
パターン3: JSON モードで出力スキーマが複雑すぎる
response_mime_type="application/json" を使うとき、response_schema に複雑なネスト構造を指定するとこのエラーが出る場合があります。スキーマを段階的に簡略化して、どこで失敗するかを二分探索すると早く特定できます。
SAFETY — コンテンツフィルタリング
SAFETY エラーは、Gemini の安全フィルターがリクエストまたはレスポンスをブロックしたときに発生します。response.text にアクセスしようとすると例外が発生する形なので、フィルターに気づかず使うとアプリがクラッシュします。
response = model.generate_content(prompt)
# ❌ safety フィルターが発動していても気づかずアクセスしてしまう
print(response.text) # → ValueError: response.text quick accessor only works when...
# ✅ finish_reason を確認してから使う
if response.candidates[0].finish_reason.name == "STOP":
print(response.text)
elif response.candidates[0].finish_reason.name == "SAFETY":
print("安全フィルターによりブロックされました")
# safety_ratings を確認して原因カテゴリを特定する
for rating in response.candidates[0].safety_ratings:
if rating.probability.name not in ("NEGLIGIBLE", "LOW"):
print(f" カテゴリ: {rating.category.name}, 確率: {rating.probability.name}")
else:
print(f"生成停止理由: {response.candidates[0].finish_reason.name}")開発段階で安全フィルターの閾値を調整したい場合、safety_settings パラメータで変更できます。ただし本番環境でこの設定を使う際は、アプリケーションのコンテキストと利用規約を十分に確認してください。
DEADLINE_EXCEEDED — タイムアウト
DEADLINE_EXCEEDED はリクエストが設定時間内に完了しなかった場合に発生します。長い文章の生成や、gemini-2.5-pro に複雑な推論を要求すると出やすいです。
google-genai クライアントのデフォルトタイムアウトは60秒前後ですが、request_options で変更できます。
import google.generativeai as genai
genai.configure(api_key="YOUR_GEMINI_API_KEY")
model = genai.GenerativeModel("gemini-2.5-pro")
# 長い文章生成や推論タスクには 120〜300 秒が目安
response = model.generate_content(
"以下のコードベースをリファクタリングして...",
request_options={"timeout": 180} # 3分
)
print(response.text)ストリーミングを使うことでタイムアウトを回避しやすくなります。ストリーミングなら最初のトークンが返ってきた時点でタイムアウトクロックがリセットされるため、長い生成でも安定します。
# ストリーミングで長文生成
for chunk in model.generate_content("長い記事を書いて...", stream=True):
print(chunk.text, end="", flush=True)
print() # 最後に改行PERMISSION_DENIED — API キー・認証エラー
PERMISSION_DENIED は API キーが無効か、権限が足りない場合に出ます。確認すべき点は次のとおりです。
- API キーが正しく環境変数にセットされているか(ターミナルで
echo $GEMINI_API_KEYで確認) - API キーが Google AI Studio のものか、Vertex AI のものかを混同していないか
- Google AI Studio で Gemini API が有効化されているか
Antigravity の設定ファイルや .env に直接 API キーを書くのではなく、環境変数経由で読み込む方法を採ることをおすすめします。誤って git commit してしまうリスクを防げます。
import os
import google.generativeai as genai
# 環境変数から API キーを取得(コードに直書きしない)
api_key = os.environ.get("GEMINI_API_KEY")
if not api_key:
raise ValueError("GEMINI_API_KEY 環境変数が設定されていません")
genai.configure(api_key=api_key)
model = genai.GenerativeModel("gemini-2.5-flash")
response = model.generate_content("テスト")
print(response.text)デバッグに迷ったら:エラー情報を丸ごとログに出す
「エラーメッセージを読んでも原因がわからない」という場合、str(e) で出力されるメッセージだけでなく、例外オブジェクト全体をログに記録すると手がかりが増えます。
import traceback
from google.api_core import exceptions as google_exceptions
try:
response = model.generate_content(prompt)
print(response.text)
except google_exceptions.GoogleAPIError as e:
# 詳細情報をすべて出力する
print(f"エラー種別: {type(e).__name__}")
print(f"gRPC ステータスコード: {e.grpc_status_code}")
print(f"メッセージ: {e.message}")
print(f"トレースバック:\n{traceback.format_exc()}")e.grpc_status_code を見ると、HTTP ステータスではなく gRPC のステータスコードが確認でき、エラーの種類をより正確に絞り込めます。
エラーコードさえ読めるようになれば、Gemini API Python の問題の8割は解決の糸口が見えてくるはずです。まずはエラーの型を確認して、このガイドの該当セクションを参考にしてみてください。