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-04-30中級

Gemini API に画像を渡しても「画像が見えません」と返るときの診断と対処

Gemini API に画像を入力したのに『画像は添付されていません』と返ってくる現象の原因を、mime_type・サイズ・SDK差・モデル選択の4視点で切り分け、コピペで動く修正コードまで一気通貫で解説します。

gemini-api279troubleshooting57multimodal24image5python103

「画像を渡したのに As an AI, I cannot see images. と返ってきた」「I don't see an attachment in your message と言われた」— Gemini API でマルチモーダル入力を試したとき、最初にぶつかる壁がこれではないでしょうか。

私自身、商品画像を解析するスクリプトを書いたときに丸一日溶かした経験があります。原因はたいていモデル側ではなくクライアント側にあって、4つのポイントを順に潰せば必ず切り分けられます。ここではその診断手順と修正コードを、実際にハマりやすい順に並べてお伝えします。

まず疑うべきは「画像が届いていない」可能性

エラーメッセージが「画像が見えない」と読める場合でも、実際には画像データそのものが API に届いていないケースが大半です。Gemini はリクエスト構造を見て画像パートが存在しないと判断したら、テキストとして「画像はないですよ」と素直に返してきます。

最初に確認すべきは次の3点です。

  • リクエストの contents 配列に 画像パートと mime_type が両方含まれているか
  • 画像のサイズが 20MB 以下か(インライン送信の上限)
  • 使っているモデルが マルチモーダル対応かgemini-2.5-flash / gemini-2.5-pro などは対応、text-embedding-004 などは非対応)

ここで「mime_type を渡していなかった」が見つかれば、それだけで解決することが多いです。

落とし穴①: mime_type は自動推定されない

新しい統合 SDK google-genai も含め、画像を bytes で渡すときは mime_type を明示しないと API 側で正しく認識してくれません。拡張子から推定してくれる、という思い込みは捨てた方が安全です。

# ❌ よくある間違い: bytes だけを渡す
from google import genai
from pathlib import Path
 
client = genai.Client(api_key="YOUR_GEMINI_API_KEY")
image_bytes = Path("product.jpg").read_bytes()
 
# このまま渡すと「画像が見えません」と返ることがある
response = client.models.generate_content(
    model="gemini-2.5-flash",
    contents=["この商品の特徴を教えてください", image_bytes],
)

正しくは types.Part.from_bytes()mime_type を必ず付けます。

# ✅ 正しい書き方: Part を作って mime_type を明示
from google import genai
from google.genai import types
from pathlib import Path
 
client = genai.Client(api_key="YOUR_GEMINI_API_KEY")
image_bytes = Path("product.jpg").read_bytes()
 
image_part = types.Part.from_bytes(
    data=image_bytes,
    mime_type="image/jpeg",  # PNG なら "image/png", WebP なら "image/webp"
)
 
response = client.models.generate_content(
    model="gemini-2.5-flash",
    contents=["この商品の特徴を教えてください", image_part],
)
print(response.text)
# 期待出力例:
# このバッグは A4 サイズの書類が入る大きさで、ショルダーストラップが…

PIL.Image オブジェクトを直接渡すルートも公式に対応していますが、それは pillow がインストールされていてかつ画像が壊れていない場合に限ります。本番運用では bytes + mime_type の方が事故が起きにくいです。

落とし穴②: 20MB を超えたら Files API に切り替える

インラインで画像を送る方法は、リクエスト全体(テキスト + 画像のすべて)が 20MB 以下 に収まるときだけ有効です。スマホで撮った高解像度写真や、PDF を画像化した複数ページのデータはあっさりこの上限を超えます。

20MB を超える場合は黙って失敗するわけではなく、リクエスト自体が 400 Bad Request413 Payload Too Large で弾かれます。受信側が画像を見られないのではなく、そもそも届いていない状態です。

# ✅ 20MB 超や複数枚を扱うなら Files API を使う
from google import genai
from google.genai import types
 
client = genai.Client(api_key="YOUR_GEMINI_API_KEY")
 
# アップロード(File オブジェクトが返る)
uploaded = client.files.upload(file="large_photo.jpg")
print(f"uploaded: name={uploaded.name}, uri={uploaded.uri}, state={uploaded.state.name}")
# 期待出力例:
# uploaded: name=files/abc123, uri=https://generativelanguage.googleapis.com/v1beta/files/abc123, state=ACTIVE
 
response = client.models.generate_content(
    model="gemini-2.5-flash",
    contents=[
        "写っている被写体の特徴を3つ挙げてください",
        uploaded,  # File オブジェクトをそのまま contents に入れる
    ],
)
print(response.text)

Files API は無料枠でも 20GB / プロジェクトの保存領域があり、48 時間でファイルが自動削除される運用です。アップロード直後に statePROCESSING のままだと推論が走らないので、画像以外(動画・PDF)の場合は ACTIVE になるまで軽く待つ処理を入れておくと安定します。

詳しい使い分けは Gemini API Files API 使い方完全ガイド と Gemini API Files API トラブルシューティングガイド を読むと、運用上の注意点まで一気にわかります。

落とし穴③: 古い SDK と新 SDK で書き方が違う

2025 年に Google が google-generativeai(旧 SDK)から google-genai(新統合 SDK)への移行を進め、画像入力の書き方が変わりました。古い記事のコードをそのままコピペすると、エラーは出ないのに「画像が見えません」と返るパターンが起きます。

旧 SDK(google-generativeai)の書き方は以下でした。

# 旧 SDK(参考・新規プロジェクトでは推奨しない)
import google.generativeai as genai
from PIL import Image
 
genai.configure(api_key="YOUR_GEMINI_API_KEY")
model = genai.GenerativeModel("gemini-1.5-flash")
img = Image.open("product.jpg")
response = model.generate_content(["説明してください", img])

これを新 SDK 環境で実行すると、google.generativeai モジュールが見つからないか、見つかっても挙動が変わっていて意図通りに画像が認識されないことがあります。新 SDK では先述の client.models.generate_content() + types.Part.from_bytes() がスタンダードです。

両 SDK の差分を網羅的に確認したい方は google-genai Python SDK 完全移行ガイド を参照してください。

画像が届いているか、ログで切り分ける

ここまでの3つを直してもまだ「画像が見えない」と返るときは、実際にリクエストへ画像パートが入ったかをログで確かめます。contents の中身を出力して、ちゃんと Part(inline_data=...) が含まれているかを目視するだけでも切り分け精度が上がります。

from google import genai
from google.genai import types
from pathlib import Path
 
client = genai.Client(api_key="YOUR_GEMINI_API_KEY")
image_bytes = Path("product.jpg").read_bytes()
image_part = types.Part.from_bytes(data=image_bytes, mime_type="image/jpeg")
 
contents = ["この画像を50字以内で説明してください", image_part]
 
# デバッグログ: 各パートの種類を出力
for i, c in enumerate(contents):
    if isinstance(c, str):
        print(f"[{i}] text: {c[:30]}...")
    elif isinstance(c, types.Part):
        if c.inline_data:
            print(f"[{i}] inline_data: mime={c.inline_data.mime_type}, "
                  f"bytes={len(c.inline_data.data)}")
        else:
            print(f"[{i}] part: {c}")
 
response = client.models.generate_content(model="gemini-2.5-flash", contents=contents)
print("---")
print(response.text)
 
# 期待出力例:
# [0] text: この画像を50字以内で説明してください...
# [1] inline_data: mime=image/jpeg, bytes=384921
# ---
# 革製のショルダーバッグ。落ち着いたブラウンで、金具はゴールド。

inline_data: mime=image/jpeg, bytes=... がログに出ているのに「画像が見えない」と返るなら、画像コンテンツ自体が真っ白・破損しているか、Safety Filter で弾かれている可能性が高くなります。Safety Filter のブロックを疑うときは、応答オブジェクトの response.prompt_feedback を見ると block_reason が確認できます。

マルチ画像のときに「一部だけ見えない」現象

もうひとつ気付きにくいのが、複数枚の画像のうち 一部だけ認識されない ケースです。1枚が壊れていたり、上限を超えていたり、対応外の形式だったりすると、Gemini はそれを黙って無視して、生きている画像だけ処理します。普段はありがたい挙動ですが、デバッグ中は混乱します。

防御策は、contents を組み立てる前に各画像をバリデーションすることです。

from pathlib import Path
from google.genai import types
 
SUPPORTED = {"image/jpeg", "image/png", "image/webp", "image/heic", "image/heif"}
MAX_INLINE_BYTES = 19 * 1024 * 1024  # 20MB制限の手前で止める
 
def to_part(path: str, mime_type: str) -> types.Part:
    if mime_type not in SUPPORTED:
        raise ValueError(f"未対応の mime_type {mime_type}: {path}")
    data = Path(path).read_bytes()
    if len(data) == 0:
        raise ValueError(f"{path} が空です")
    if len(data) > MAX_INLINE_BYTES:
        raise ValueError(f"{path}{len(data)} バイト(Files API推奨)")
    return types.Part.from_bytes(data=data, mime_type=mime_type)
 
parts = [
    to_part("front.jpg", "image/jpeg"),
    to_part("back.png", "image/png"),
]
contents = ["2枚の商品写真を比較し、相違点を要約してください"] + parts

API に投げる前にローカルで弾いておけば、エラーメッセージから問題画像を一発で特定できます。「画像が見えません」という曖昧な返答に悩まされずに済む、地味ですが効く対策です。

Vertex AI を使っている場合の補足

AI Studio の API キー方式から Vertex AI に切り替えている場合(リージョン要件や高い割り当てが理由のことが多いはずです)も、ここまでの落とし穴はそのまま当てはまります。違うのはクライアント初期化だけで、types.Part.from_bytes() も Files API もまったく同じ書き方です。

# Vertex AI 版の同じ修正
from google import genai
from google.genai import types
from pathlib import Path
 
client = genai.Client(
    vertexai=True,
    project="your-gcp-project-id",
    location="us-central1",
)
 
image_bytes = Path("product.jpg").read_bytes()
image_part = types.Part.from_bytes(data=image_bytes, mime_type="image/jpeg")
 
response = client.models.generate_content(
    model="gemini-2.5-flash",
    contents=["この商品の特徴を教えてください", image_part],
)
print(response.text)

Vertex AI 固有のハマりポイントは、generativelanguage.googleapis.com 用の API キーが Vertex AI(aiplatform.googleapis.com)では一切通らない、という点です。「画像が見えない」ではなく 401 Unauthenticated が出ているなら、コードがクライアントモードを取り違えていないかを最初に疑ってください。

Node.js / TypeScript を使っている場合

@google/genai Node.js SDK でも同じ問題が起きますが、特有の落とし穴が2つあります。1つ目はブラウザ環境では Buffer が使えないこと、2つ目はプロパティ名がキャメルケースで mimeType になることです。

// ✅ Node.js / TypeScript の正しい書き方
import { GoogleGenAI } from "@google/genai";
import { readFileSync } from "node:fs";
 
const ai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });
 
const imageBytes = readFileSync("product.jpg");
const response = await ai.models.generateContent({
  model: "gemini-2.5-flash",
  contents: [
    { text: "この商品の特徴を教えてください" },
    {
      inlineData: {
        mimeType: "image/jpeg",                    // ← snake_case ではなく camelCase
        data: imageBytes.toString("base64"),       // Buffer ではなく base64 文字列
      },
    },
  ],
});
console.log(response.text);

data は base64 エンコード済みの文字列を渡す必要があります。Buffer をそのまま渡すと Python 版で mime_type を忘れたときと同じ症状(黙って画像なしリクエストになる)が出ます。

最終チェックリスト

ここまでで解決しないときの確認順序を、検出しやすい順に並べておきます。

  • 使用モデルが gemini-2.5-flash / gemini-2.5-pro など 画像対応モデル
  • Part.from_bytes(data=..., mime_type=...)mime_type を明示 しているか
  • 画像の 総容量が 20MB 以下 か(超えるなら Files API へ)
  • ファイルが JPEG / PNG / WebP / HEIC / HEIF のいずれか(GIF・SVG は不可)
  • 古い google-generativeai ではなく google-genai を使っているか
  • レスポンスの prompt_feedback.block_reasonSAFETY弾かれていないか
  • 一度 Google AI Studio に同じ画像を貼って モデル側で見えるか を確認

このうち上から3つを潰すだけで、私の経験では9割の「画像が見えない」現象が解決しました。マルチモーダル入力の基本は Gemini API マルチモーダル完全ガイド でも丁寧に整理しているので、合わせて目を通しておくと再発を防げます。

切り分けの順番を1枚のメモに書き出して手元に置いておくと、次に同じ症状が出ても3分で原因を特定できるはずです。今日のうちに、最近詰まっていた画像入力スクリプトに mime_type を1行足してみてください。多くの場合、それだけで「見えなかった画像」が見えるようになります。

シェア

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

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

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

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

関連記事

API / SDK2026-05-17
Gemini API で画像バッチ分析の INVALID_ARGUMENT エラーを診断する
Gemini API で複数画像を一括分析するとき INVALID_ARGUMENT エラーが出て詰まった経験はありませんか。MIMEタイプ・サイズ制限・リクエスト構造という3つの原因を診断し、File API と inline data を使い分けて根本解決する実践ガイドです。
API / SDK2026-06-14
Gemini API の本文が途中で切れる — finish_reason: MAX_TOKENS を検知して続きを継ぎ直す実装メモ
長文生成で末尾が文の途中でぷつりと切れる。原因の多くは finish_reason: MAX_TOKENS です。例外も 200 のまま静かに混入するこの事故を検知し、続きを継ぎ足して全文を取り戻す実装を、思考トークンの落とし穴とあわせてまとめました。
API / SDK2026-06-12
Gemini API の空応答を finish_reason から逆引きする — 診断フロー・再試行分類・監視の実務
response.text が空になる問題は candidates・prompt_feedback・finish_reason の3層で診断できます。思考トークンによる出力枯渇の検出、再試行可否の分類器、空応答率の監視まで、本番で運用している実装をまとめました。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →