Gemini 2.5 Pro や 3.1 系で動いていたコードを Gemini 3.2 に切り替えた途端に壊れた、という経験をした開発者はかなり多いと思います。私自身も個人開発のアプリで同じ状況に直面し、原因を特定するまでに数時間かかりました。
Gemini 3.2 は機能面で大幅に強化されていますが、その分 API の仕様変更点も多く、それまでの書き方がそのまま通じないケースが増えています。私が実際にぶつかった(または開発者コミュニティで頻繁に報告されている)5つのエラーパターンを、具体的なコードとともに整理しました。
エラー 1: モデルIDが正しくない(400 INVALID_ARGUMENT)
最もよく見かけるのが、モデルIDの指定ミスです。Gemini 3.2 のリリース当初、多くの開発者が gemini-3-2-pro や gemini-3.2-pro-latest といった自己流の書き方をしてハマりました。
import google.generativeai as genai
# ❌ 動かないパターン
model = genai.GenerativeModel("gemini-3-2-pro") # ハイフン区切りは3.2では変更あり
model = genai.GenerativeModel("gemini/3.2-pro") # スラッシュ記法は無効
model = genai.GenerativeModel("gemini-3.2-pro-latest") # "latest" サフィックスは不定期更新
# ✅ 正しいパターン
model = genai.GenerativeModel("gemini-3.2-pro") # ドット区切りが正式
model = genai.GenerativeModel("gemini-3.2-flash") # 軽量版はこちら公式ドキュメントの更新が遅れることがあるため、Gemini 3.2 API 実装ガイド に記載されているモデルID一覧を定期的に確認することをおすすめします。また、以下のコードで利用可能なモデルを一覧取得できます。
import google.generativeai as genai
genai.configure(api_key="YOUR_GEMINI_API_KEY")
for m in genai.list_models():
if "gemini-3.2" in m.name:
print(m.name, "—", m.supported_generation_methods)出力例(2026年5月時点):
models/gemini-3.2-pro — ['generateContent', 'streamGenerateContent']
models/gemini-3.2-flash — ['generateContent', 'streamGenerateContent']
エラー 2: コンテキスト上限オーバー(400 RESOURCE_EXHAUSTED)
Gemini 3.2 Pro のコンテキストウィンドウは 2M トークン超に拡張されましたが、それが原因で思わぬ問題が発生することがあります。
問題のパターン
長いチャット履歴を変換せずにそのまま渡していると、いつの間にかトークン上限を超えてエラーになります。特に注意が必要なのは、「2M トークン対応だから大丈夫」と油断して、画像や PDF を大量に添付するケースです。
# ❌ 問題のあるパターン — 会話履歴が無制限に蓄積する
conversation_history = []
def chat(user_input):
conversation_history.append({"role": "user", "parts": [user_input]})
response = model.generate_content(conversation_history)
conversation_history.append({"role": "model", "parts": [response.text]})
return response.text# ✅ 修正版 — トークン数を監視してローリングサマリーを挿入する
MAX_TOKENS = 1_500_000 # 2Mの75%を上限に設定
def chat_with_limit(user_input, history):
history.append({"role": "user", "parts": [user_input]})
# トークン数チェック
token_count = model.count_tokens(history).total_tokens
if token_count > MAX_TOKENS:
# 古い会話を要約して圧縮
summary = summarize_history(history[:-10]) # 最新10件は保持
history = [{"role": "user", "parts": [f"[これまでの会話要約]: {summary}"]}] + history[-10:]
response = model.generate_content(history)
history.append({"role": "model", "parts": [response.text]})
return response.text, historyコンテキスト圧縮については、Gemini 2.5 Pro から Gemini 3.2 Pro への移行プレイブック でも詳しく扱っています。
エラー 3: ストリーミング応答が途中で切れる
Gemini 3.2 では Thinking Mode がデフォルトで有効になるケースがあり、ストリーミング中に予期しない STOP が入って応答が中断することがあります。
症状
GenerateContentResponse(
done=True,
candidates=[Candidate(
content=Content(parts=[Part(text='')]),
finish_reason=FinishReason.STOP,
)]
)
ストリーミングコールバックが呼ばれたのに text が空だった場合、これは思考プロセス(Thinking Token)の送出タイミングと実際のテキスト出力が分離したことが原因です。
# ❌ 問題のある書き方 — 空チャンクでエラーになる
for chunk in model.generate_content(prompt, stream=True):
print(chunk.text) # ValueError: Response has no candidates (or all finished)
# ✅ 修正版 — 空チャンクをスキップする
for chunk in model.generate_content(prompt, stream=True):
if chunk.candidates and chunk.candidates[0].content.parts:
for part in chunk.candidates[0].content.parts:
if hasattr(part, 'text') and part.text:
print(part.text, end='', flush=True)Thinking Mode を明示的に制御したい場合は、以下のように設定します。
from google.generativeai.types import GenerationConfig
# Thinking を無効にする(レイテンシ重視の場合)
config = GenerationConfig(
thinking_config={"thinking_budget": 0}
)
response = model.generate_content(prompt, generation_config=config)
# Thinking を有効にして予算を指定(精度重視の場合)
config_thinking = GenerationConfig(
thinking_config={"thinking_budget": 10000} # トークン数で指定
)エラー 4: レート制限エラー(429 RESOURCE_EXHAUSTED)
2026年に入ってから Gemini 3.2 の利用者が急増した影響で、無料枠・低プランのユーザーは特にレート制限に引っかかりやすくなっています。
個人開発アプリを運営していて感じるのは、朝9時〜10時のピーク帯と深夜2時〜3時は特に制限が厳しくなる傾向があることです。これは Google のサーバー負荷と関係していると推測しています。
import time
import random
from google.api_core import exceptions
def generate_with_retry(model, prompt, max_retries=3):
"""指数バックオフ + ジッターでレート制限に対応する"""
for attempt in range(max_retries):
try:
return model.generate_content(prompt)
except exceptions.ResourceExhausted as e:
if attempt == max_retries - 1:
raise
# 指数バックオフ: 1秒 → 2秒 → 4秒 + ランダムジッター
wait = (2 ** attempt) + random.uniform(0, 1)
print(f"レート制限 — {wait:.1f}秒後にリトライ(試行 {attempt + 1}/{max_retries})")
time.sleep(wait)
except exceptions.ServiceUnavailable:
if attempt == max_retries - 1:
raise
time.sleep(5 + random.uniform(0, 2))詳しいレート制限対策は Gemini API レート制限エラーを完全解決するトラブルシューティングガイド にまとめています。
エラー 5: Function Calling のスキーマが通らない(400 INVALID_ARGUMENT)
Gemini 3.2 では Function Calling のスキーマバリデーションが以前より厳格になりました。3.1 以前のコードをそのまま移行すると、スキーマエラーで詰まるケースが増えています。
よく見かけるエラーメッセージ
google.api_core.exceptions.InvalidArgument: 400 Function declarations must not have 'optional' keys.
# ❌ Gemini 3.1 以前で動いていたスキーマ(3.2 では失敗する場合がある)
tools_old = [
{
"function_declarations": [{
"name": "get_weather",
"description": "指定した都市の天気を取得",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string"},
"unit": {"type": "string", "optional": True} # ← NG: "optional" キーは非推奨
},
"required": ["city"]
}
}]
}
]
# ✅ Gemini 3.2 に対応した書き方
tools_new = [
{
"function_declarations": [{
"name": "get_weather",
"description": "指定した都市の天気を取得します。unit を省略した場合は摂氏で返します。",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "都市名(例: Tokyo, Osaka)"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "温度単位。省略時は celsius を使用"
# "optional" キーは使わず、"required" リストから外す
}
},
"required": ["city"] # unit は required に含めない = 省略可能
}
}]
}
]スキーマデバッグのコツ
スキーマエラーの原因を素早く特定するには、まず最小限のスキーマで動作確認してから、徐々にプロパティを追加する方法が確実です。
# デバッグ用: 最小構成でスキーマを検証する
def validate_schema(model, tool_schema):
try:
response = model.generate_content(
"テスト: 東京の天気を教えて",
tools=tool_schema
)
print("✅ スキーマ検証OK")
return True
except Exception as e:
print(f"❌ スキーマエラー: {e}")
return False全体を振り返って — 移行チェックリストとして使う
Gemini 3.2 への移行でエラーが出たとき、まずこの5つを確認することで原因を絞り込めます。
- モデルID は
gemini-3.2-pro/gemini-3.2-flashの形式か - コンテキストが 2M トークンに近づいていないか(
count_tokensで確認) - ストリーミング受信時に空チャンクのスキップ処理があるか
- 429 エラーには指数バックオフのリトライが実装されているか
- Function Calling スキーマに
optionalキーや古い書き方が残っていないか
Gemini のバージョンが上がるたびに挙動が変わることがありますが、公式のリリースノートを追うよりも、実際に手を動かして試すほうが早く理解できることが多いです。私自身もそうしながら、少しずつ知識を積み上げてきました。同じ課題に取り組んでいる方の参考になれば幸いです。