You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
gemini-3.5-flash-lite rejects zero budget at thinking mode #2936
With the latest version of python-genai, gemini-3.5-flash-lite is not able to work when "thinkingBudget=0", with "thinkingBudget=None" works, but other models working fine with a budget of zero.
But, using a simple script with python httpx (no google-genai involved) I got this:
┌─────────────────────────────────────┬─────────────────┐
│ gemini-3.5-flash-lite │ Raw REST result │
├─────────────────────────────────────┼─────────────────┤
│ thinkingBudget: 0 │ 400 │
├─────────────────────────────────────┼─────────────────┤
│ omitted │ 200 OK │
├─────────────────────────────────────┼─────────────────┤
│ -1 (dynamic) │ 200 OK │
├─────────────────────────────────────┼─────────────────┤
│ 512 │ 200 OK │
├─────────────────────────────────────┼─────────────────┤
│ (control) gemini-2.5-flash-lite + 0 │ 200 OK │
└─────────────────────────────────────┴─────────────────┘
I tested all other models, including 3.8 family without issues, this is the only model with this problem.
Hi @phenobarbital, Thanks for reaching out us!
To help us understand the issue, could you please share a code snippet of what you've tried so far?
Thanks
import asyncio
import json
import os
import aiohttp
from google import genai
from google.genai import types
from parrot.conf import config
API_KEY = config.get("GOOGLE_API_KEY") or os.getenv("GOOGLE_API_KEY") or os.getenv("GEMINI_API_KEY")
async def test_raw_rest(session, model, thinking_budget, label):
url = f"https://generativelanguage.googleapis.com/v1beta/models/{model}:generateContent?key={API_KEY}"
generation_config = {}
if thinking_budget is not None:
generation_config["thinkingConfig"] = {"thinkingBudget": thinking_budget}
payload = {
"contents": [{"parts": [{"text": "Say hello in 5 words."}]}],
}
if generation_config:
payload["generationConfig"] = generation_config
try:
async with session.post(url, json=payload) as resp:
status = resp.status
text = await resp.text()
try:
data = json.loads(text)
if status == 200:
cand = data.get("candidates", [{}])[0]
content = cand.get("content", {}).get("parts", [{}])[0].get("text", "")
print(f"[REST] {model} | {label} -> HTTP {status} OK: {content.strip()[:60]}")
else:
err = data.get("error", {}).get("message", text[:100])
print(f"[REST] {model} | {label} -> HTTP {status} ERROR: {err}")
except Exception:
print(f"[REST] {model} | {label} -> HTTP {status} Raw: {text[:100]}")
return status
except Exception as e:
print(f"[REST] {model} | {label} -> EXCEPTION: {e}")
return None
async def test_sdk(client, model, thinking_budget, thinking_level, label):
th_cfg = None
if thinking_budget is not None or thinking_level is not None:
kwargs = {}
if thinking_budget is not None:
kwargs["thinking_budget"] = thinking_budget
if thinking_level is not None:
kwargs["thinking_level"] = thinking_level
th_cfg = types.ThinkingConfig(**kwargs)
gen_cfg = types.GenerateContentConfig(thinking_config=th_cfg) if th_cfg else None
try:
resp = await client.aio.models.generate_content(
model=model,
contents="Say hello in 5 words.",
config=gen_cfg,
)
print(f"[SDK] {model} | {label} -> SUCCESS: {resp.text.strip()[:60] if resp.text else 'EMPTY'}")
return 200
except Exception as e:
print(f"[SDK] {model} | {label} -> EXCEPTION: {type(e).__name__}: {e}")
return str(e)
async def main():
print("=" * 60)
print("TESTING GEMINI-3.5-FLASH-LITE & CONTROL MODELS")
print(f"SDK version: {genai.__version__}")
print("=" * 60)
models_to_test = [
"gemini-3.5-flash-lite",
"gemini-2.5-flash-lite",
]
async with aiohttp.ClientSession() as session:
print("\n--- 1. RAW REST (v1beta) ---")
for m in models_to_test:
for tb, label in [
(None, "omitted"),
(0, "thinkingBudget: 0"),
(-1, "thinkingBudget: -1"),
(512, "thinkingBudget: 512"),
]:
await test_raw_rest(session, m, tb, label)
print("\n--- 2. GOOGLE-GENAI SDK ---")
client = genai.Client(api_key=API_KEY)
for m in models_to_test:
for tb, tl, label in [
(None, None, "omitted"),
(0, None, "thinking_budget=0"),
(-1, None, "thinking_budget=-1"),
(512, None, "thinking_budget=512"),
(None, "MINIMAL", "thinking_level='MINIMAL'"),
(None, "LOW", "thinking_level='LOW'"),
]:
await test_sdk(client, m, tb, tl, label)
if __name__ == "__main__":
asyncio.run(main())
When is called with plain aiohttp calls I got this:
--- 1. RAW REST (v1beta) ---
[REST] gemini-3.5-flash-lite | omitted -> HTTP 200 OK: Hello, how are you today?
[REST] gemini-3.5-flash-lite | thinkingBudget: 0 -> HTTP 400 ERROR: Request contains an invalid argument.
[REST] gemini-3.5-flash-lite | thinkingBudget: -1 -> HTTP 200 OK: Hi, nice to meet you.
[REST] gemini-3.5-flash-lite | thinkingBudget: 512 -> HTTP 200 OK: Hello there, how are you?
[REST] gemini-2.5-flash-lite | omitted -> HTTP 200 OK: Hello there, how are you?
[REST] gemini-2.5-flash-lite | thinkingBudget: 0 -> HTTP 200 OK: Hello, it's great to see you.
[REST] gemini-2.5-flash-lite | thinkingBudget: -1 -> HTTP 200 OK: Hello! Wishing you a nice day.
[REST] gemini-2.5-flash-lite | thinkingBudget: 512 -> HTTP 200 OK: Hello, how are you doing?
but with google-genai (version: 2.18.1) I got:
[SDK] gemini-3.5-flash-lite | omitted -> SUCCESS: Hello there, how are you?
[INFO] 2026-09-04 12:34:58,055 google_genai.models(models.py:8757) :: AFC is enabled with max remote calls: 10.
[SDK] gemini-3.5-flash-lite | thinking_budget=0 -> EXCEPTION: ClientError: 400 INVALID_ARGUMENT. {'error': {'code': 400, 'message': 'Request contains an invalid argument.', 'status': 'INVALID_ARGUMENT'}}
the unrecognized thinkingBudget=0 only affects gemini-3.5-flash-lite, any other flash models (e.g. 3.8) or older (like 3.1 or 2.5) are not affected by this issue.
I was using thinkingBudget=0 on any model but gemini-3.5-flash-lite.
as conclusion:
Key Inconsistencies for the Incident Report
SDK Docstring vs Reality:
The google-genai SDK docstring (types.py:13606) states:
│ "Starting from Gemini 3.5 models, the old thinking_budget will no longer be supported and will result in a user error if set. Instead, users should use the thinking_level parameter to control the maximum thinking depth."
However, thinking_budget is not completely unsupported on 3.5: -1 and 512 succeed without errors. Only 0 is rejected.
No Mechanism to Disable Thinking:
types.ThinkingLevel only defines MINIMAL, LOW, MEDIUM, and HIGH. It does not provide an OFF or NONE level. Since thinking_budget=0 raises a 400 error, developers migrating from 2.5 have no way to turn thinking off.
Opaque Error Message:
Pro models explicitly explain invalid budget configurations (e.g. "Budget 0 is invalid. This model only works in thinking mode"). gemini-3.5-flash-lite only outputs the generic message: "Request contains an invalid argument.")
Hi @phenobarbital, thanks for the fantastic report and test script! We ran it and perfectly reproduced the 400 error with thinkingBudget=0 on gemini-3.5-flash-lite, as well as the missing OFF state in the new thinking levels. I've escalated this straight to the engineering and API teams to get both issues sorted, thanks again for flagging this.
Activity
Venkaiahbabuneelam commentedon Sep 3, 2026
Hi @phenobarbital, Thanks for reaching out us!
To help us understand the issue, could you please share a code snippet of what you've tried so far?
Thanks
phenobarbital commentedon Sep 4, 2026
@Venkaiahbabuneelam yes, sure!
I tested directly using this snippet:
When is called with plain aiohttp calls I got this:
but with google-genai (version: 2.18.1) I got:
the unrecognized thinkingBudget=0 only affects gemini-3.5-flash-lite, any other flash models (e.g. 3.8) or older (like 3.1 or 2.5) are not affected by this issue.
I was using thinkingBudget=0 on any model but gemini-3.5-flash-lite.
as conclusion:
Key Inconsistencies for the Incident Report
The google-genai SDK docstring (types.py:13606) states:
│ "Starting from Gemini 3.5 models, the old thinking_budget will no longer be supported and will result in a user error if set. Instead, users should use the thinking_level parameter to control the maximum thinking depth."
However, thinking_budget is not completely unsupported on 3.5: -1 and 512 succeed without errors. Only 0 is rejected.
types.ThinkingLevel only defines MINIMAL, LOW, MEDIUM, and HIGH. It does not provide an OFF or NONE level. Since thinking_budget=0 raises a 400 error, developers migrating from 2.5 have no way to turn thinking off.
Pro models explicitly explain invalid budget configurations (e.g. "Budget 0 is invalid. This model only works in thinking mode"). gemini-3.5-flash-lite only outputs the generic message: "Request contains an invalid argument.")
kkorpal commentedon Sep 8, 2026
Hi @phenobarbital, thanks for the fantastic report and test script! We ran it and perfectly reproduced the 400 error with thinkingBudget=0 on gemini-3.5-flash-lite, as well as the missing OFF state in the new thinking levels. I've escalated this straight to the engineering and API teams to get both issues sorted, thanks again for flagging this.