Nano Banana 2 在 Gemini API 里的模型 ID 是 gemini-3.1-flash-image。报错时先别急着重试:只有 429 里的速率类错误、408 和 5xx 值得有上限地退避重试;400、401、402、403、404 要改请求、密钥或账单;每日配额用完要等重置;IMAGE_SAFETY 这类内容拦截要改提示词或参考图;地区不支持则重试多少次都一样。
还要先确认两件事:代码里的模型名是不是已经下线的 gemini-3.1-flash-image-preview,以及你用的是 Interactions API 还是 generateContent。两种接口报错的写法不同,前者是小写的 no_image、quota_exceeded,后者是大写的 NO_IMAGE、RESOURCE_EXHAUSTED。
Nano Banana 2 报错对照表:按日志里的信号查处理
下表按“你在日志里看到什么”排列。错误代码列同时写了 Interactions API 的小写代码和 generateContent 常见的大写写法。
| 你看到的 | 问题在哪 | 先做什么 | 要不要重试 |
|---|---|---|---|
404,model_not_found,模型名带 -preview | 模型 ID | 改成 gemini-3.1-flash-image,预览 ID 已于 2026 年 6 月 25 日停用 | 不要 |
400,invalid_request、parameter_unknown 或 INVALID_ARGUMENT | 请求写法 | 按 message 改参数,常见的是 image_size 写成小写 1k | 不要 |
400,FAILED_PRECONDITION,message 是 "User location is not supported for the API use" | 地区 | 发起调用的所在地不在支持列表,见下文地区一节 | 不要 |
400,failed_precondition,message 与计费有关 | 账单前提 | 检查项目是否关联了可用的结算账号 | 不要 |
401,authentication | 密钥 | key 缺失、写错或已过期 | 不要 |
403,permission_denied,或 "Your API key was reported as leaked" | 权限 / 泄露 | 查 key 的项目权限;被判定泄露的 key 只能换新 | 不要 |
402,payment_required | 预付费余额 | 余额用完,充值或开启自动充值 | 不要 |
429,rate_limit_exceeded 或 too_many_requests | 每分钟 / 每秒上限 | 指数退避加随机抖动,降低并发 | 可以,有上限 |
429,quota_exceeded | 每日配额 | 等太平洋时间午夜重置,或申请提额 | 当天不要 |
429 RESOURCE_EXHAUSTED,10 分钟内调用了大量高价请求 | 按消费金额的限速 | 放慢 4K 等高价请求的节奏 | 稍等再试 |
500,api_error | Google 服务端 | 退避重试,持续出现再联系支持 | 可以,有上限 |
503,UNAVAILABLE,"This model is currently experiencing high demand" | 模型容量 | 退避重试,持续时降低并发 | 可以,有上限 |
504,deadline_exceeded | 截止时间 | 去掉或放宽客户端 deadline | 调整后再试 |
499,cancelled | 你的客户端 | 客户端在完成前断开了 | 查明原因再发 |
HTTP 200,finishReason: NO_IMAGE 或 no_image | 生成结果 | 读返回的文字和 finishMessage,用最小请求对比 | 改输入后再试 |
HTTP 200,IMAGE_SAFETY、IMAGE_PROHIBITED_CONTENT 或 image_safety | 内容政策 | 改提示词或参考图 | 原样重试无效 |
没有 candidates,只有 promptFeedback.blockReason | 提示被拦截 | 按 blockReason 改输入;OTHER 可能违反条款或属于不支持的用法 | 原样重试无效 |
finishReason: PUP_LIMITED_DISABLED | 账户受限 | 账户因违反使用政策被限制,改提示词没用 | 不要 |
错误代码和 HTTP 状态的对应关系来自 Google 的 API 错误参考(截至 2026 年 9 月 20 日更新);重试范围来自故障排查文档,其中明确写着只重试 429、408 和 5xx,不要重试 400、402、403。
先确认模型 ID 和调用方式
预览 ID 已经下线
Nano Banana 2 在 2026 年 2 月 26 日以 gemini-3.1-flash-image-preview 发布,5 月 28 日推出正式版 gemini-3.1-flash-image,预览 ID 同日被宣布弃用,并在 2026 年 6 月 25 日停止服务(见 Gemini API 更新日志)。6 月之前写的示例代码如果还用预览 ID,照抄就会请求一个已经停用的模型。错误参考把这种情况归为 model_not_found,HTTP 404,建议核对模型名。下线后具体返回什么 message,公开文档没有给出样例,所以只要看到 404 就先查模型字符串。
同系列的其他 ID 也值得核对一遍:Nano Banana 2 Lite 是 gemini-3.1-flash-lite-image,Nano Banana Pro 是 gemini-3-pro-image,最早的 Nano Banana 是 gemini-2.5-flash-image。2026 年 9 月 18 日起,Google 把“2.5 系列模型”限制为只对以前用过的用户开放,新项目改用新模型。更新日志没有写明这是否包括 gemini-2.5-flash-image,也没写被拒时返回什么代码;新项目如果在旧图片模型上碰到拒绝,直接换到 3.1 系列更省事。
两种接口,错误出现在不同位置
Google 的图片生成文档现在只展示 Interactions API(POST /v1beta/interactions)。按 Interactions API 说明,它自 2026 年 6 月起正式可用,推荐新项目使用;原来的 generateContent 被称为旧版接口,但“仍然完全支持”,并没有弃用。两种接口都能调用 Nano Banana 2,出错时的样子却不一样:
| Interactions API | generateContent | |
|---|---|---|
| 请求级错误 | HTTP 状态码加 {"error": {"code": "quota_exceeded", "message": "..."}},code 是小写下划线 | HTTP 状态码加错误体,状态名是大写,例如 RESOURCE_EXHAUSTED、UNAVAILABLE |
| 没出图 | 错误参考列出 no_image、image_safety 等代码;interaction 对象还有 status(completed、failed、incomplete 等)和 errors 字段 | 通常是 HTTP 200,原因在 candidates[].finishReason 或 promptFeedback.blockReason |
| 图片在哪 | steps[].content[] 里 type 为 image 的块,SDK 提供 interaction.output_image | candidates[].content.parts[] 里的 inlineData |
Interactions API 的流式请求(stream: true)出错时,会在 SSE 流里发出 event_type 为 error 的事件,结构同样是 code 加 message。
两点容易漏看。第一,HTTP 非 2xx 时也要读响应体:同样是 400,message 可能是参数错误,也可能是地区不支持;同样是 429,code 决定该退避还是等明天。第二,Interactions API 的错误参考只把 no_image、image_safety 列为错误代码,没有写清它们是随 HTTP 错误返回,还是出现在 status 为 failed 的 interaction 的 errors 里,所以解析时两处都要看。

上图按 generateContent 画出了三层信号:HTTP 状态、生成结束原因、调用方自己的超时。Interactions API 的请求级错误同样属于第一层,no_image、image_safety 属于第二层,只是字段位置不同。
用最小请求确认链路
排查时先用一个最简单的请求确认密钥、项目、模型和地区都没问题,再把复杂输入一项项加回去。下面是 Interactions API 的写法,把 HTTP 状态码和响应体分开保存:
curl -s -o nb2-probe.json -w "HTTP %{http_code}\n" \
-X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
-H "x-goog-api-key: ${GEMINI_API_KEY:?先设置 GEMINI_API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"model": "gemini-3.1-flash-image",
"input": "生成一张白色背景上的蓝色陶瓷杯产品图",
"response_format": {"type": "image", "image_size": "1K"}
}'还在用 generateContent 的项目,对应的最小请求是:
curl -s -o nb2-probe.json -w "HTTP %{http_code}\n" \
-X POST "https://generativelanguage.googleapis.com/v1beta/models/gemini-3.1-flash-image:generateContent" \
-H "x-goog-api-key: ${GEMINI_API_KEY:?先设置 GEMINI_API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"contents": [{"parts": [{"text": "生成一张白色背景上的蓝色陶瓷杯产品图"}]}],
"generationConfig": {"responseModalities": ["IMAGE"]}
}'最小请求成功而原请求失败,问题就在输入、参数或并发上;最小请求也失败,再看密钥、账单、地区和服务状态。Nano Banana 2 是付费模型,成功出图就按输出计费,1K 标准价约 $0.067 一张(Gemini API 价格页),探测请求不要放进循环里批量跑。
400、401、403、404:先改请求或密钥
这一组错误的共同点是:原样再发一次,结果不会变。
400 invalid_request 或 parameter_unknown 表示请求体格式或参数有问题。Nano Banana 2 上常见的几种:
image_size必须用大写K(512px对应的 0.5K、1K、2K、4K),文档明确写着小写的1k会被拒绝。0.5K 只有 Nano Banana 2 支持,Nano Banana 2 Lite 只支持 1K。- 参考图最多 14 张,其中物体图最多 10 张、人物图最多 4 张。
- 模型卡片列出 Nano Banana 2 不支持函数调用、结构化输出、缓存、代码执行、URL 上下文、Live API,也不支持 Flex 和 Priority 两种推理档位;在请求里带上这些选项属于请求端错误。每种情况具体返回哪个代码,文档没有逐一列出。
- 路径里的 API 版本要对。故障排查文档提醒,Beta 功能只在
/v1beta下可用。
还有一种不报错的情况值得注意:参数被忽略时,请求照样返回 200。GitHub 上有人报告,通过 Vertex AI 调用正式版 gemini-3.1-flash-image 时,无论 imageSize 设成 1K、2K 还是 4K,拿到的都是约 1K 的图(js-genai #1682,单个报告,状态不明)。对尺寸有要求的流程,应该在保存前检查输出图片的实际像素。
401 authentication 是 key 缺失、无效或过期。403 permission_denied 是这个 key 对资源没有权限,先查它属于哪个项目、项目是否启用了 Gemini API。Google 还会主动封禁已知公开泄露的 key,这时会看到 "Your API key was reported as leaked. Please use another API key."。被封的 key 不会恢复,只能在 AI Studio 新建一个,并检查 key 的保管方式;如果因泄露产生了意外费用,按故障排查文档的建议提交账单支持工单。
404 model_not_found 回到上一节:先查模型名。
地区限制:中国大陆、香港、澳门不在支持列表
Google 公布的 Gemini API 与 AI Studio 可用地区(2026 年 4 月 28 日更新)包括台湾、日本、新加坡、美国等,但没有中国大陆、香港和澳门。所以“Gemini API 国内可以用吗”的答案是:官方不支持。
在不支持的地区调用时,开发者报告收到的是 400、状态 FAILED_PRECONDITION、message 为 "User location is not supported for the API use" 的错误(这段文字来自用户报告,官方文档里没有这个样例;更早的报告里也有显示为 403 的)。要注意,官方对 failed_precondition 的定义是“前提条件未满足,例如未开启计费”,所以同一个 400 FAILED_PRECONDITION 既可能是地区问题,也可能是账单问题,要看 message 判断。
可用地区页面对 Colab 用户说得很明确:限制按 Colab 实例所在的地区判断,而不是按用户本人所在的地区。其他调用方式官方没有单独说明;如果本地测试正常、部署到另一台服务器后才报地区错误,先查那台服务器所在的地区。
这个错误等待和重试都不会消失。Google 在地区页面上建议不在列表里的用户改用 Gemini Enterprise Agent Platform 里的 Gemini API,但该平台能否面向中国大陆客户提供服务,公开页面没有说明,不能直接当作国内方案。各项 Gemini 服务的地区与年龄要求可以在Gemini 目前不支持你所在的地区:先确认是哪项服务不可用里逐项核对。
三种 429:速率、每日配额和消费限速
429 在 Nano Banana 2 上至少有三种来源,处理方式不同:
| 类型 | 怎么认出来 | 怎么处理 |
|---|---|---|
| 每分钟 / 每秒上限(RPM、TPM、图片模型的 IPM) | Interactions API 返回 rate_limit_exceeded 或 too_many_requests | 指数退避加随机抖动,降低并发,把突发流量摊平 |
| 每日配额(RPD) | Interactions API 返回 quota_exceeded | 等太平洋时间午夜重置,或申请提额;当天重试只会继续失败 |
| 按消费金额的限速 | 429 RESOURCE_EXHAUSTED,通常出现在短时间内大量生成高分辨率图片时 | 稍等后再试,降低高价请求的频率,经常碰到可以申请提高限额 |
generateContent 的 429 都显示为 RESOURCE_EXHAUSTED,光看状态名分不出是哪一种,要读 message,再到 AI Studio 对照当前用量。
几条会改变判断的规则都来自 Gemini API 速率限制文档:
- 限额按项目计算,不按 API key 计算。 同一个项目里换一个 key 不会让 429 消失。
- 每日请求数在太平洋时间午夜重置。
- 各层级的实际限额只在 AI Studio 里显示,官方也说明这些数字“不保证”。速率限制文档没有给出 Nano Banana 2 各层级的固定 RPM 或 IPM,网上流传的具体数字无法从官方页面核对。
- Nano Banana 2 在价格页上的免费层标注为“不可用”,没有绑定结算账号的项目用不了它。这种情况下具体返回什么错误,官方没有写明。想先免费试用,可以看Nano Banana 免费使用:官方入口、额度与地区限制里整理的官方入口。
按消费金额的限速有多容易碰到
除了请求数,Google 还按滚动 10 分钟窗口内的消费金额限速:Tier 1 为 $10,Tier 2 为 $50,Tier 3 为 $200,超出就返回 429 RESOURCE_EXHAUSTED。这项限速是否适用取决于账户的计费历史和层级。
用 Nano Banana 2 标准价粗算 Tier 1 在 10 分钟里最多能出多少张图(只算输出费用):
| 分辨率 | 每张输出价格 | $10 ÷ 单价 |
|---|---|---|
| 4K | $0.151 | 约 66 张 |
| 2K | $0.101 | 约 99 张 |
| 1K | $0.067 | 约 149 张 |
| 0.5K | $0.045 | 约 222 张 |
Tier 2 是这些数字的 5 倍,Tier 3 是 20 倍。实际能跑的量会更少:输入 token、思考 token、使用 Google 搜索建立依据的费用、以及失败重试都会占用同一笔金额,RPM 或 IPM 也可能先到上限。这张表只说明一件事:Tier 1 项目 10 分钟内集中跑几十张 4K 图,即使每分钟请求数不多,也可能收到 429。
429 与 AI Studio 网页端额度提示的区别,见AI Studio 提示达到速率限制怎么办:先分清哪份额度;层级资格、项目与结算账号的关系和查看当前限额的位置,见Gemini API 分层速率限制:查清当前限额与 429 原因。
402 和月度上限:账单停用不会自己恢复
按 Gemini API 计费文档,新用户默认使用预付费(Prepay)方式。预付费余额降到 $0 时,这个结算账号下所有项目的所有 API key 会同时停用,请求返回 402 Payment Required,直到充值为止。计费数据大约有 10 分钟延迟,批量任务可能在停用前继续消费,余额会显示为负数,这时服务同样暂停,负数部分从下次充值里扣除。开启自动充值可以避免中断。
余额明明大于 0 却停了,官方给出的解释是可能碰到了当前层级的月度消费上限。上限按结算账号计算,汇总所有关联项目:Tier 1 为 $250,Tier 2 为 $2,000,Tier 3 为 $20,000 到 $100,000。到达上限后,所有关联项目暂停到下个月 1 日,可以申请提高上限。以 Tier 1 的 $250 粗算,只算输出费用,大约是 1,655 张 4K 或 3,731 张 1K 图。这种暂停具体返回哪个错误代码,文档没有写明,所以看到不熟悉的拒绝时,先去 AI Studio 的消费页面看看是否到了上限。AI Studio 也可以给单个项目设置月度消费上限(实验功能),同一结算账号下有多个项目时可以用它分配额度。
402 和月度上限都属于“不要重试”的一类:重试不会让余额变多,只会让日志更难读。
500、503、504 与超时:有上限地退避
500 api_error 是 Google 服务端的意外错误,官方建议重试,持续出现就联系支持。503 UNAVAILABLE 表示服务暂时过载或不可用,用户看到的 message 常是 "This model is currently experiencing high demand"。这两种错误都不是你的请求写错了,Google 也没有公布恢复时间,正确做法是指数退避:第一次等 1 秒左右,之后 2 秒、4 秒、8 秒,加上随机抖动,并设定最大次数。
504 deadline_exceeded 是请求没能在截止时间内完成。官方建议去掉客户端 deadline 设置或把它调大,让服务端使用默认值。499 cancelled 则是你的客户端在完成前断开了连接,官方说明这种情况“无需处理”,但你要弄清是谁先断开的:浏览器、应用服务器,还是中间的反向代理。
Nano Banana 2 的调用时间和输入量、分辨率、思考级别都有关。Gemini 3.x 模型默认开启思考,Nano Banana 2 的 thinking_level 可设为 minimal(默认)或 high,high 更慢,思考 token 也要计费。4K 输出、high 思考和多张参考图叠在一起时,过短的客户端超时会把本来能完成的请求截断。这时服务端是否已经完成生成、是否计费,Google 没有说明;批量任务重发前,先在 AI Studio 里看一眼用量,避免重复生成。思考级别对耗时和费用的影响见Nano Banana 2 思考级别怎么选:Minimal、High 与 API 设置。
不要让重试次数相乘
官方 SDK 默认已经带自动重试。以 Python SDK 为例,它会对超时、网络问题、429 和 5xx 自动重试最多 4 次,初始间隔约 1 秒,最长间隔 60 秒。如果在 SDK 外面再套一层 4 次的重试,一次业务调用最多会发出 4 × (1 + 4) = 20 次请求,每一次都占配额。两层之间只保留一层重试。
直接用 REST 调用时,可以参考下面的 Python 示例。它把一次响应归到六种动作之一,只对 408、429(每日配额除外)和 5xx 退避,次数和总时长都有上限;Interactions API 与 generateContent 的响应都能识别。依赖 requests,url、headers、payload 按上面 curl 的内容填写:
import random
import time
import requests
RETRY_HTTP = {408, 429, 500, 502, 503, 504}
STOP_REASONS = {
"SAFETY", "PROHIBITED_CONTENT", "BLOCKLIST", "SPII", "RECITATION",
"IMAGE_SAFETY", "IMAGE_PROHIBITED_CONTENT", "IMAGE_RECITATION", "IMAGE_OTHER",
"LANGUAGE", "CONTENT_BLOCKED", "PUP_LIMITED_DISABLED",
}
def classify(status: int, body: dict) -> dict:
"""把一次响应归到一个动作:ok / backoff / wait_reset / fix / stop / inspect。"""
err = body.get("error") if isinstance(body, dict) else None
if status >= 400 or err:
err = err or {}
# Interactions API 的 code 是小写字符串;generateContent 的 code 是数字,状态名在 status
code = err.get("code") if isinstance(err.get("code"), str) else err.get("status", "")
message = err.get("message", "")
if code == "quota_exceeded":
return {"action": "wait_reset", "code": code, "message": message}
if status in RETRY_HTTP:
return {"action": "backoff", "code": code or status, "message": message}
if "location is not supported" in message:
return {"action": "stop", "code": code or status, "message": message}
return {"action": "fix", "code": code or status, "message": message}
# Interactions API:图片在 steps[].content[] 里,type 为 image
if "steps" in body or "status" in body:
images = [
c for s in body.get("steps") or [] for c in s.get("content") or []
if c.get("type") == "image" and c.get("data")
]
if images:
return {"action": "ok", "images": images}
codes = [str(e.get("code", "")) for e in body.get("errors") or []]
blocked = any(c.upper() in STOP_REASONS for c in codes)
return {"action": "stop" if blocked else "inspect",
"status": body.get("status"), "codes": codes}
# generateContent:先看有没有候选,再看 parts 和 finishReason
candidates = body.get("candidates") or []
if not candidates:
reason = (body.get("promptFeedback") or {}).get("blockReason")
return {"action": "stop", "blockReason": reason}
cand = candidates[0]
parts = (cand.get("content") or {}).get("parts") or []
images = [p["inlineData"] for p in parts if p.get("inlineData")]
if images:
return {"action": "ok", "images": images}
reason = cand.get("finishReason")
return {
"action": "stop" if reason in STOP_REASONS else "inspect",
"finishReason": reason,
"finishMessage": cand.get("finishMessage"),
"text": " ".join(p.get("text", "") for p in parts)[:200],
"usage": body.get("usageMetadata"),
}
def generate_with_retry(url, headers, payload, max_attempts=4, budget_s=300):
"""只对暂态错误退避重试,次数和总时长都有上限。
客户端超时会直接抛出异常:此时服务端结果未知,不自动重发。"""
deadline = time.monotonic() + budget_s
for attempt in range(1, max_attempts + 1):
resp = requests.post(url, headers=headers, json=payload, timeout=(10, 240))
try:
body = resp.json()
except ValueError:
body = {}
result = classify(resp.status_code, body)
result["http_status"] = resp.status_code
if result["action"] != "backoff" or attempt == max_attempts:
return result
delay = min(2 ** (attempt - 1), 30) * random.uniform(1.0, 1.5)
if time.monotonic() + delay > deadline:
return result
time.sleep(delay)几个动作的含义:fix 是改请求、密钥或账单后再发;wait_reset 是等每日配额重置;stop 是内容拦截、账户受限或地区不支持,原样重试没有意义;inspect 是 200 却没图、原因不在拦截列表里(例如 NO_IMAGE),需要人工看返回的文字和 finishMessage。generateContent 的 429 都会被归为 backoff,如果退避几轮仍然失败,按上一节的方法判断是不是每日配额或消费限速。
HTTP 200 OK 却没有图片:NO_IMAGE、IMAGE_SAFETY 等原因
这是最容易被当成“接口坏了”的情况。请求本身成功了,只是这次生成没有产出图片,原因写在响应里。
generateContent:先看有没有候选,再看 blockReason
generateContent 参考规定,API 要么返回全部候选,要么一个都不返回;完全没有 candidates 只说明提示本身有问题,这时看 promptFeedback.blockReason:
SAFETY:出于安全原因屏蔽了提示,查看safetyRatings了解是哪个类别。OTHER:原因未知。故障排查文档补充说,看到BlockedReason.OTHER时,请求或回复可能违反了服务条款,或属于不支持的用法。参考图被拦时也可能出现在这里。BLOCKLIST、PROHIBITED_CONTENT:包含屏蔽名单里的词或禁止内容。IMAGE_SAFETY:因不安全的图片生成内容被屏蔽。
有候选但没有图片时,看候选的 finishReason。和图片有关的几个值(含义参照官方中文文档):
| finishReason | 含义 | 下一步 |
|---|---|---|
NO_IMAGE | 模型本应生成图片,但却未生成任何图片 | 读返回的文字;确认请求里要了图片输出,提示词明确要求生成或修改图片;用最小请求对比 |
IMAGE_SAFETY | 由于生成的图片包含违规内容,生成已停止 | 改提示词或参考图 |
IMAGE_PROHIBITED_CONTENT | 生成的图片包含其他禁止的内容 | 改提示词或参考图 |
IMAGE_RECITATION | 因存在重复内容而停止 | 让提示和参考图更有独创性 |
IMAGE_OTHER | 其他杂项问题导致停止 | 简化输入后对比 |
PUP_LIMITED_DISABLED | 账户因违反禁止使用政策而受限或停用 | 属于账户问题,改提示词无效 |
返回了文字、finishReason 是 STOP,却没有 inlineData,往往是模型只回了文字,先检查请求里的输出类型和提示词有没有明确要求出图。
Interactions API:看 status、errors 和图片块
Interactions API 把 safety、prohibited_content、image_safety、image_prohibited_content、image_recitation、image_other、content_blocked 等列为“生成被拦截”类代码,官方建议是修改输入后再试;no_image 则归在生成错误里,含义是模型未能生成图片。拿到响应后,检查 steps 里有没有 type 为 image 的块,再看 interaction 的 status 和 errors。
把安全设置调低有用吗
多半没有用。按 安全设置文档,可调的四类过滤(骚扰、仇恨言论、色情、危险内容)默认已经关闭,而儿童安全等核心保护始终生效、不能调整。由此推断,把安全阈值改成 BLOCK_NONE 一般不会让 IMAGE_SAFETY 或 PROHIBITED_CONTENT 消失。能做的是改写提示词、换掉触发拦截的参考图,而不是用重试去碰运气。提示词层面的具体改法见Gemini 不出图或 IMAGE_SAFETY 怎么排查?修复思路汇总。
生成失败的请求会不会扣费
分三种情况看:
- 返回 400 或 500 的请求:计费文档写明不收 token 费用,但仍然计入配额。所以对
400反复重试,钱不多花,额度却在消耗。 - HTTP 200 但以
IMAGE_SAFETY、NO_IMAGE结束的请求:Google 的计费和价格页面都没有说明怎么计费。可以核对的办法是看这类响应里的usageMetadata(promptTokenCount、candidatesTokenCount、thoughtsTokenCount),再和 AI Studio 的账单记录对照。 - 客户端超时、没拿到响应的请求:服务端是否完成、是否计费,文档没有说明。
通过第三方网关调用时,失败怎么收费由网关自己规定,和 Google 的规则不同。比如 laozhang.ai(新加坡 YingTu Technology Pte. Ltd. 运营的 API 网关)的 Nano Banana 文档写明:它对 gemini-3.1-flash-image 按次收费,2026 年 9 月 24 日价格配置为每次 $0.055,是服务商自定的价格;HTTP 200 但没有图片(包括上游安全拦截)按一次调用扣费;客户端超时时服务端可能已经扣费,重试前要先查调用日志;返回 429 或 503、没有进入生成的请求通常不扣费。它只接受 Gmail 注册,能否开通以企业白名单审核为准。网关返回的错误代码与 Google 原始错误的对应关系,要以网关自己的文档和调用日志为准。
什么时候停止重试,求助时带什么

上图是一个通用的停止与升级流程。放到 Nano Banana 2 上,还要补一条:429 quota_exceeded 不进退避循环,而是等每日配额重置。遇到以下任何一种情况,就停止自动重试:
400、401、402、403、404,包括地区不支持的FAILED_PRECONDITION;429 quota_exceeded,或者 AI Studio 显示已到月度消费上限;IMAGE_SAFETY、PROHIBITED_CONTENT、blockReason等内容拦截,以及PUP_LIMITED_DISABLED;NO_IMAGE还没用最小请求对比过;- 退避达到次数上限或总时长预算,
503仍在持续; - 客户端超时,而服务端结果还没确认。
需要向 Google 支持或团队求助时,一句“还是不行”解决不了问题。准备一份去掉密钥和敏感内容的记录:
- 时间范围(注明时区)、调用的接口(Interactions API 或 generateContent)、完整 URL 路径、API 版本和模型 ID;
- HTTP 状态码、
error.code/status、完整的message; - 响应里的 interaction
id或responseId、modelVersion、usageMetadata; finishReason、finishMessage、promptFeedback,以及返回了哪些类型的内容;- 每次尝试的耗时、客户端超时设置、SDK 和外层各自的重试次数;
- 同一项目、同一模型下最小请求是否成功。
恢复的判断标准也要明确:在你实际使用的同一条链路上,最小请求返回了可以解码的图片,然后原来的批量任务在受控并发下也能跑完。只看到 HTTP 200,或者只是日志里不再出现 NO_IMAGE,还不够。
常见问题
Gemini API 在国内可以用吗?
官方不支持。Gemini API 与 AI Studio 的可用地区列表里没有中国大陆、香港和澳门,在这些地区发起的调用会被拒绝,重试无效。Google 建议不在列表里的用户看 Gemini Enterprise Agent Platform,但该平台是否面向中国大陆客户提供服务,公开页面没有说明。
同一个项目换一个 API key,能躲开 429 吗?
不能。速率限制按项目计算,不按 key 计算。想提高上限,要么等层级随消费自动升级,要么在 AI Studio 申请提额;如果是 quota_exceeded,就等太平洋时间午夜重置。
Gemini API 报 503 要等多久才能恢复?
Google 没有公布恢复时间。按 1 秒、2 秒、4 秒、8 秒的节奏加随机抖动退避,设好次数上限;持续失败时降低并发或推迟批量任务,并记录时间范围和响应 id,方便向支持反馈。
用了很久的 gemini-3.1-flash-image-preview 突然报 404,怎么办?
预览 ID 已在 2026 年 6 月 25 日停止服务,把模型名改成 gemini-3.1-flash-image。改名后如果变成 400,按当前的图片生成文档核对参数,比如 image_size 必须用大写 K。
选 Nano Banana 2 还是 Pro,报错和处理方式有区别吗?
错误代码和处理方式在两个模型上是一样的,差别在价格、画质和速度,因此同样的消费限速下能出的图片数量也不同。怎么选见Nano Banana 2 vs Pro 怎么选:价格、画质、速度与场景。



