跳到正文

Nano Banana 2 API 报错:429、503、NO_IMAGE 怎么处理

预览 ID 已下线会报 404;三种 429 处理各不相同;402 是预付费余额用完;HTTP 200 却没图要看 finishReason 或 no_image;地区不支持时重试无效。

•••27 分钟阅读•故障排查
深色背景示意图:400、429、503、NO_IMAGE 和超时五个标签分别归入 HTTP 请求结果、生成结束原因、调用方 deadline 三栏,再对应修请求、上限重试、解析响应与查未知结果

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_errorGoogle 服务端退避重试,持续出现再联系支持可以,有上限
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 APIgenerateContent
请求级错误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_imagecandidates[].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 里,所以解析时两处都要看。

分层示意图:顶部 HTTP 请求层列出 400、429、503;中间 GenerateContent 生成结果层由 finishReason 分出 image part、NO_IMAGE 与 IMAGE_SAFETY;底部调用方或网关 deadline 层标出 timeout 后没有 response body、结果可能未知

上图按 generateContent 画出了三层信号:HTTP 状态、生成结束原因、调用方自己的超时。Interactions API 的请求级错误同样属于第一层,no_image、image_safety 属于第二层,只是字段位置不同。

用最小请求确认链路

排查时先用一个最简单的请求确认密钥、项目、模型和地区都没问题,再把复杂输入一项项加回去。下面是 Interactions API 的写法,把 HTTP 状态码和响应体分开保存:

bash
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 的项目,对应的最小请求是:

bash
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 的内容填写:

python
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 原始错误的对应关系,要以网关自己的文档和调用日志为准。

什么时候停止重试,求助时带什么

重试与停止流程图:已保存原始证据后按错误类型或原因分成五列,分别是 400、429/503/408/5xx、NO_IMAGE、安全或 policy 拦截、timeout,其中暂态错误一列进入指数退避加 jitter、带尝试次数上限和总时间预算的循环,底部是硬停止门和携带证据包的升级流程

上图是一个通用的停止与升级流程。放到 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 怎么选:价格、画质、速度与场景。

发现内容有误,或遇到文中没覆盖的问题?请把文章地址和你看到的情况发到 hi@laozhang.ai,核实后我们会更新正文。