GEMINI LABEN
NANOLITE — Nano Banana 2 Liteが登場しました。Googleで最も速く、最もコスト効率の高いGemini Imageモデルで、軽量な画像生成を安く回したい用途に向いていますOMNIFLASH — Gemini Omni Flashがpublic previewになりました。ネイティブにマルチモーダルなモデルで、企業や開発者が独自の動的な動画ワークフローを構築できますAGENTS — Managed Agentsが拡張されました。background: trueでサーバー側の非同期実行とポーリング、リモートMCPサーバー連携、対話をまたぐ認証情報のリフレッシュに対応しますMEMORY — Memory BankのIngestEvents APIが一般提供になりました。イベントの取り込みとメモリ生成を分離し、コンテンツを継続的にストリームできますTHROUGHPUT — Provisioned Throughputで、同一モデル・同一リージョンに対して最大7件の保留オーダーを提出できるようになりましたDEPRECATE — 画像生成モデルは8月17日に、Gemini Enterprise Agent PlatformのGrok 4.1系は8月20日に停止される予定ですNANOLITE — Nano Banana 2 Liteが登場しました。Googleで最も速く、最もコスト効率の高いGemini Imageモデルで、軽量な画像生成を安く回したい用途に向いていますOMNIFLASH — Gemini Omni Flashがpublic previewになりました。ネイティブにマルチモーダルなモデルで、企業や開発者が独自の動的な動画ワークフローを構築できますAGENTS — Managed Agentsが拡張されました。background: trueでサーバー側の非同期実行とポーリング、リモートMCPサーバー連携、対話をまたぐ認証情報のリフレッシュに対応しますMEMORY — Memory BankのIngestEvents APIが一般提供になりました。イベントの取り込みとメモリ生成を分離し、コンテンツを継続的にストリームできますTHROUGHPUT — Provisioned Throughputで、同一モデル・同一リージョンに対して最大7件の保留オーダーを提出できるようになりましたDEPRECATE — 画像生成モデルは8月17日に、Gemini Enterprise Agent PlatformのGrok 4.1系は8月20日に停止される予定です
記事一覧/API / SDK
API / SDK/2026-05-10中級

Gemini API で大きなPDFや動画を inlineData で送ると RESOURCE_EXHAUSTED — Files API への切り替え判断

Gemini API で大きなPDFや動画ファイルを inlineData で送って RESOURCE_EXHAUSTED が出る原因と、Files API への現実的な移行手順を、個人開発の現場感覚でまとめます。

gemini-api279files-api4troubleshooting57pdf6inline-data

先日、累計5,000万DLを超える自分のアプリ事業の延長で組んでいた「ユーザーがアップロードしたPDFをGeminiが要約する」内部ツールが、20MBほどのPDFを処理した瞬間に RESOURCE_EXHAUSTED で止まりました。テスト用の数MBのPDFでは順調に動いていたので、原因が分からずログを眺めていた数十分は地味につらかったです。

結論から書くと、inlineData で送れる容量にはリクエスト全体で20MBという壁があり、Base64 エンコードでさらに約4/3倍に膨らむため、見かけ15MB前後のファイルでも上限に当たります。本番運用では Files API に切り替える判断をどこで入れるかが鍵になります。本稿はその切り替えラインと、実際の移行手順を丁寧に追っていきます。

inlineData が大きいファイルで失敗する理由

Gemini API のリクエストには、メタデータも含めて1リクエスト合計約20MBの上限が設けられています。inlineData でファイルを直接埋め込む方式は、内部で Base64 にエンコードされるため、元のバイナリサイズに対して約 4/3 倍 に膨らみます。

具体的には次のようなイメージです。

  • 元ファイル 12MB → Base64 後 約16MB → リクエスト全体 16MB+α → ギリギリ通る
  • 元ファイル 16MB → Base64 後 約21MB → 上限超過 → RESOURCE_EXHAUSTED
  • 元ファイル 30MB(動画) → Base64 後 約40MB → 即エラー

実際のエラーメッセージは次のような形で返ってきます。

google.api_core.exceptions.ResourceExhausted: 429 RESOURCE_EXHAUSTED.
{'error': {'code': 429, 'message': 'Resource has been exhausted (e.g. check quota).', 'status': 'RESOURCE_EXHAUSTED'}}

メッセージだけ見ると「クォータ超過」と勘違いしやすいのですが、ペイロードサイズが原因のときも同じステータスで返ってくるのが厄介な点です。

切り替え判断のシンプルなルール

公式ドキュメントには上限値の記載はありますが、「どこで Files API に切り替えるか」の判断基準までは踏み込んで書かれていません。10年以上個人で開発を続けてきた経験から、私は次のラインを目安にしています。

  • ファイル合計が 15MB を超えそうなら最初から Files API
  • 同じファイルを 2回以上 API に渡す予定があるなら Files API
  • 検証用のスクリプトや単発処理は inlineData で十分
  • ユーザーアップロードを受け付ける本番システムは Files API ベース固定

特に2点目は見落としやすいのですが、Files API を使えば一度アップロードしたファイルを48時間 URI で参照し続けられるため、再送信のコストとレイテンシを大幅に削減できます。

Files API への移行コード(Python)

実際に手を動かして比較します。まずは「動かなくなる前」の inlineData パターンです。

# inlineData 方式 — 小さいファイル向け
from google import genai
from google.genai import types
import pathlib
 
client = genai.Client(api_key="YOUR_API_KEY")
 
pdf_bytes = pathlib.Path("report.pdf").read_bytes()
 
response = client.models.generate_content(
    model="gemini-2.5-flash",
    contents=[
        types.Part.from_bytes(data=pdf_bytes, mime_type="application/pdf"),
        "このPDFの主要な論点を3つに絞って日本語で要約してください。",
    ],
)
print(response.text)

PDFが10MB以下なら問題ありません。これが20MB近くになると、ある日突然 RESOURCE_EXHAUSTED が出始めます。次が Files API に切り替えた版です。

# Files API 方式 — 15MB超や再利用前提のファイル向け
from google import genai
import pathlib, time
 
client = genai.Client(api_key="YOUR_API_KEY")
 
# 1. アップロード(バックグラウンドで処理が走る)
uploaded = client.files.upload(file="report.pdf")
 
# 2. 処理完了を待つ(大きい動画やPDFは数秒〜数十秒)
while uploaded.state.name == "PROCESSING":
    time.sleep(2)
    uploaded = client.files.get(name=uploaded.name)
 
if uploaded.state.name == "FAILED":
    raise RuntimeError(f"Upload failed: {uploaded.state}")
 
# 3. URI を contents に渡して通常通り推論
response = client.models.generate_content(
    model="gemini-2.5-flash",
    contents=[
        uploaded,
        "このPDFの主要な論点を3つに絞って日本語で要約してください。",
    ],
)
print(response.text)
 
# 期待する出力例:
# 1. 〇〇に関する2026年の市場動向 ...
# 2. 主要プレイヤー間のシェア変化 ...
# 3. 来年に向けた成長領域の3つの軸 ...

ポイントは2つあります。動画やページ数の多いPDFは statePROCESSING のまま返ってくることがあるため、必ず完了待ちのループを挟むこと。そして、アップロード結果オブジェクトをそのまま contents に渡せること(旧SDKのように URI 文字列を組み立てる必要はありません)。

TypeScript / Node.js での書き方

JavaScript SDK でも考え方は同じです。Node.js や Cloudflare Workers で運用している場合の最小構成を載せておきます。

// Files API @google/genai 版(Node.js / Bun)
import { GoogleGenAI } from "@google/genai";
 
const ai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY! });
 
async function summarise(pdfPath: string) {
  // アップロード(すぐ返る。処理はサーバー側で継続)
  let file = await ai.files.upload({
    file: pdfPath,
    config: { mimeType: "application/pdf" },
  });
 
  // 完了待ち
  while (file.state === "PROCESSING") {
    await new Promise((r) => setTimeout(r, 2000));
    file = await ai.files.get({ name: file.name! });
  }
  if (file.state === "FAILED") throw new Error("upload failed");
 
  const result = await ai.models.generateContent({
    model: "gemini-2.5-flash",
    contents: [
      { fileData: { fileUri: file.uri!, mimeType: file.mimeType! } },
      { text: "このPDFの主要な論点を3つに絞って日本語で要約してください。" },
    ],
  });
  return result.text;
}

Python SDK と異なるのは、JavaScript 側は contents にファイルオブジェクトを直接渡せず、fileData パートを手で組み立てる必要がある点です。mimeType の指定漏れは静かに失敗する典型例なので、レビュー時にここだけは必ず確認するようにしています。

ありがちな副作用と回避策

切り替え後にハマりやすい落とし穴を3つ挙げます。これも実際にアプリ運用中にぶつかったものです。

ひとつ目は 48時間の有効期限 です。Files API にアップロードしたファイルは48時間で自動削除されます。バッチ処理を分割して走らせると、後半で File URI not found が出ることがあるので、長時間ジョブでは「ジョブ開始時に再アップロード」を原則にしておくと安全です。詳しい挙動はGemini API: ファイルURIが再起動後に見つからないエラーの解消法で扱っています。

ふたつ目は 同名ファイルでも内容が違えば別URI という点です。upload() は呼び出すたびに新しいリソースを作るため、同じファイルを何度も処理する場合は URI を辞書に保持して使い回すのが定石です。

3つ目は アップロード自体の失敗 です。ネットワークが不安定な環境ではタイムアウトすることがあるので、リトライを実装するか、後述の Cloud Storage 経由ルートに切り替える判断も必要になります。100MBを超えるような大型ファイルはCloud Storage 経由の100MBファイル処理パイプラインが現実的です。

個人開発での使い分け(実践メモ)

私は2014年から個人でアプリ開発を続けていて、AdMob 収益のピーク時には月150万円を超える規模で運用していました。その経験から学んだのは、「コストとレイテンシは設計初期に決まる」という単純な事実です。

たとえば壁紙アプリでユーザーが投稿した画像をAIが分類するパイプラインなら、画像は基本的に1MB以下なので inlineData で十分です。一方、アート活動として手がけている高解像度の作品ファイル(数十MBのRAW画像など)を解析する際は、最初から Files API でアップロードして、複数モデルに横断的に推論させるほうがコストも時間も合理的です。

判断に迷ったら、「そのファイルをこのリクエスト1回しか使わないか?」を自分に問うのが一番速いです。Yesなら inlineData、Noや不明なら Files API。これだけで、今回のような RESOURCE_EXHAUSTED の地味な事故はほぼ防げます。

ファイル処理のさらに詳しい運用パターンはGemini API: Files API トラブルシューティング完全ガイドに整理しています。


最後に1つだけ次のアクションを示します。今すでに inlineData でファイルを送っているコードがあるなら、ファイルサイズを取得してログに出すコードを1行入れてみてください。15MBを超えるリクエストが1日に何件出ているか可視化されると、移行判断が一気に楽になります。同じ詰まりに遭遇している方の助けになれば嬉しいです。

シェア

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

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

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

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

API / SDK2026-05-02
Gemini API のPDF入力で詰まったときの原因切り分けと解決法
Gemini API でPDFを送ったのに本文が返ってこない、サイズ制限に引っかかる、ページ数が多くて落ちる—そんな現場のつまずきを症状ごとに切り分けて、最短ルートで直していきます。
API / SDK2026-07-12
長尺PDFの章ごと要約で、まる一章が要約から消えていたとき — 被覆率を計測して取りこぼしを塞ぐ運用メモ
章ごと要約→全体再結合は長尺PDFに効きますが、抽出漏れや再結合で一章がまるごと消えても要約は素知らぬ顔で完走します。被覆率という一つの数字で取りこぼしを検知し、消えた章だけ再実行する監査つきパイプラインを実装で示します。
API / SDK2026-07-01
AI Studio で通ったプロンプトが API では静かに崩れるとき — 差分を計測して切り分ける運用メモ
AI Studio では完璧に動いたプロンプトが、自分のコードから Gemini API を呼ぶと空応答や 404 になる。目視ではなく、設定差と finish_reason・使用トークン・解決モデル名を機械的に記録する小さなハーネスで、原因別に切り分ける運用手順をまとめました。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →