GEMINI LABEN
FLASH — Gemini 3.5 FlashがGAとなり、gemini-flash-latestの実体として利用できますAGENTS — Gemini APIのManaged Agentsがパブリックプレビューとなり、Googleホストの隔離Linuxサンドボックスで自律実行できますSTUDIO — Google AI Studioにプロジェクト単位の支出上限(spend caps)が追加され、ネイティブAndroid vibe codingにも対応しましたLIVE — 音声対音声でリアルタイム対話するGemini 3.1 Flash Live Previewが公開されましたIMAGE — 最速・低コストの画像モデルNano Banana 2 Liteが提供され、Gemini Omni FlashもAPIでプレビュー公開されていますLYRIA — 音楽生成モデルLyria 3(clip-preview / pro-preview)が新たに利用できますFLASH — Gemini 3.5 FlashがGAとなり、gemini-flash-latestの実体として利用できますAGENTS — Gemini APIのManaged Agentsがパブリックプレビューとなり、Googleホストの隔離Linuxサンドボックスで自律実行できますSTUDIO — Google AI Studioにプロジェクト単位の支出上限(spend caps)が追加され、ネイティブAndroid vibe codingにも対応しましたLIVE — 音声対音声でリアルタイム対話するGemini 3.1 Flash Live Previewが公開されましたIMAGE — 最速・低コストの画像モデルNano Banana 2 Liteが提供され、Gemini Omni FlashもAPIでプレビュー公開されていますLYRIA — 音楽生成モデルLyria 3(clip-preview / pro-preview)が新たに利用できます
記事一覧/開発ツール
開発ツール/2026-07-09上級

例外にならない失敗を型で閉じる — Gemini API のレスポンスを判別可能ユニオンに正規化する

HTTP 200 なのに本文が空、という失敗は try/catch では捕まりません。finishReason と blockReason を判別可能ユニオンに正規化し、never による網羅性チェックで処理漏れをコンパイル時に潰す設計をまとめました。

Gemini API175TypeScript8エラーハンドリング型安全本番運用45

プレミアム記事

深夜、壁紙アプリの説明文生成バッチが「成功 1,842 件」と表示したまま終わりました。翌朝、Firestore を覗くと空文字のドキュメントが 20 件ほど混ざっていました。

例外は一つも投げられていません。HTTP ステータスは全て 200。SDK も何も文句を言いませんでした。ただ response.text が空文字だっただけです。

このとき私が書いていたコードは、こういう形でした。

try {
  const res = await ai.models.generateContent({ model, contents });
  await save(res.text ?? "");   // ← ここが空文字を静かに通す
} catch (e) {
  logger.error(e);
}

個人開発では、こういう失敗の見つかり方が一番こたえます。誰も監視していない時間帯に、静かにデータだけが痩せていきます。

try/catch は「投げられた失敗」しか捕まえません。Gemini API の失敗の多くは、投げられずに、正常なレスポンスの形をして返ってきます。この記事は、その取りこぼしを型システムで塞ぐまでの実装記録です。

Gemini API の失敗は三層に分かれています

整理してみると、失敗は発生場所によって三層に分かれていました。

捕まえ方
トランスポート層タイムアウト、DNS 解決失敗、接続断例外が投げられる
HTTP 層400 INVALID_ARGUMENT、429、500、503例外が投げられる
意味論層candidates 空、finishReason: SAFETY / MAX_TOKENS / RECITATION投げられない。自分で見る

上二層は既に多くの記事で語られていますし、私も429 の見分け方についての記事で扱いました。問題は三層目です。

意味論層の失敗は、SDK にとっては成功です。レスポンスは組み立てられ、promptFeedbackcandidates[0].finishReason に事情が書き込まれ、そのまま返されます。呼び出し側が読まなければ、それは無かったことになります。

私が空文字を保存してしまったのは、まさにこの層でした。

起こりうる結果を、まず全部書き出す

型を書く前に、実際のレスポンスがどんな形を取りうるかを列挙しました。SDK のレスポンスから読める分岐は、私の用途では次の5つに収まりました。

  1. promptFeedback.blockReason が立っている(入力が止められた。candidates は存在しない)
  2. candidates が空配列(モデルが何も返さなかった)
  3. finishReason: "STOP" で本文あり(唯一の成功)
  4. finishReason"MAX_TOKENS" / "SAFETY" / "RECITATION" / "OTHER"(出力側で止まった)
  5. finishReason: "STOP" なのに本文が空文字(構造化出力でスキーマに合わず、空を返してくる場合に遭遇しました)

5番目は特に厄介でした。finishReason だけを見て成功と判定すると、静かに空文字が通ります。前掲のバッチが 20 件の空ドキュメントを作ったのは、この経路です。

つまり判定は「finishReason が STOP か」ではなく、「STOP であり、かつ本文が非空か」でなければなりません。当たり前のようでいて、コードにはこの かつ が書かれていませんでした。

ここまでお読みいただきありがとうございます。

この記事の続きを読む

この先には、実装コードやベンチマーク結果など、実務でお役に立てる内容をご用意しています。このサイトは広告を掲載しておらず、サーバーや開発にかかる費用はメンバーの皆様のご支援で成り立っています。もしお役に立てていましたら、ご支援いただけますと大変ありがたいです。

この記事で得られること
HTTP 200 で返る5種類の失敗(空 candidates / SAFETY / MAX_TOKENS / RECITATION / OTHER)を漏れなく列挙する方法
判別可能ユニオンと never チェックで、新しい finishReason の追加をコンパイルエラーとして検出する実装
失敗種別ごとのリトライ可否表と、30日間の実運用ログから得た失敗内訳の実測値
Stripe による安全な決済 · いつでもキャンセル可能

この記事を購入する

この先の内容をすべてお読みいただけます。一度のご購入で、いつでも何度でもアクセスできます。このサイトは広告を掲載しておらず、皆さまのご支援がサーバー費用などの運営を支えています。

または
メンバーシップなら全記事が読み放題 →
シェア

お読みいただきありがとうございます

Gemini Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

関連記事

開発ツール2026-05-24
Streamlit と Gemini で社内 BI を本番運用する — 認証・コスト最適化・キャッシュ・可観測性の設計メモ
Streamlit + Gemini API のデータ分析アプリをマルチユーザー認証つきの社内 BI として本番運用するための設計メモ。認証層・コスト最適化・結果キャッシュ・レート制限・可観測性まで実装ベースで整理しました。
開発ツール2026-04-22
Gemini API × Cloud Tasks で作る非同期AIジョブキュー — タイムアウトとリトライを設計から解く
Cloud Run のタイムアウトと Gemini API のレート制限に挟まれて落ちる同期実装から、Cloud Tasks を軸にした非同期ジョブキュー設計へ移行する実践ガイドです。リトライ・DLQ・進捗通知まで本番で通る形で解説します。
開発ツール2026-04-04
Gemini API × SaaS 収益化 2026 — ゼロから月収10万円を目指す設計・実装・運用の全手順
Gemini API を核に据えた SaaS プロダクトで継続的な収益を生み出すための完全設計図。アーキテクチャ設計・TypeScript 実装・Stripe 課金・Cloudflare Workers デプロイ・ユーザー獲得まで、実際のコードと数値で体系的に解説します。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →