2026-07-28

Migrating off the deprecated google.generativeai SDK to google.genai

A real production bug: the old google.generativeai Python SDK has no way to set thinking_budget, so Gemini 3.x models burn their whole token budget on reasoning and return MAX_TOKENS on valid prompts. Here is the fix.

If you are still importing google.generativeai in Python, you have probably seen the FutureWarning on every import and ignored it — it is deprecated, but it still works, so why bother migrating? Here is why: that SDK has no way to set thinking_budget, and Gemini 3.x models (gemini-3.5-flash, gemini-3.1-pro-preview, and the rest of the family) default to spending almost the entire max_output_tokens budget on internal reasoning tokens before writing the visible answer.

The failure mode is not a crash. It is finish_reason=MAX_TOKENS on a completely valid prompt, with 8 to 35 characters of actual answer text — because the model used the rest of the budget thinking, and the old SDK gives you no lever to stop it.

A real example

A small open-source project (a movie-metadata scraper that uses Gemini to enrich records) hit this directly and filed issue #107. Their workaround before the real fix: manually add every new thinking-capable model to a GEMINI_EXCLUDED_MODELS list so the pipeline would skip straight to a non-thinking fallback model. That works until the next Gemini 3.x release, at which point the same MAX_TOKENS failure comes back and the excluded-models list has to be updated again — reactive and fragile, in the reporter's own words.

Worth noting: their fix scope grew once they looked closely. They expected 2 files to touch, and found 5 production files wired into a shared error classifier — if your codebase calls the Gemini SDK from more than one place (a summarizer, a retry/rotation layer, a usage-logging breadcrumb), budget on finding more call sites than you expect.

The fix

Three parts, in order:

1. Swap the dependency: google-generativeaigoogle-genai in your requirements file, and remove every import google.generativeai from src/. The FutureWarning disappearing on import is your signal the old SDK is fully gone, not just aliased.

2. Set the budget explicitly on every call: thinking_config={"thinking_budget": 0} (or a nonzero budget if you want the model to reason, just not unboundedly) — the new google.genai SDK is what actually exposes this parameter. Without it, you are back to the same MAX_TOKENS failure, just on the new SDK instead of the old one.

3. If your response-handling code branches on finish_reason (retry on MAX_TOKENS, fall back to another model on SAFETY, etc.), re-run those paths against the new SDK's response shape before you trust it in production — the reporter's test plan explicitly called out preserving that rotation logic 1:1, not just getting a 200 back.

Why this belongs here

This is the same root cause covered on /parameters and /thinking-level — Gemini 3.x models think by default, and if nothing in your code tells them not to (or tells them how much), that budget comes out of your visible answer, not on top of it. The SDK migration is a separate, mechanical piece of that same problem: you cannot set thinking_budget at all on google.generativeai, deprecated or not, so staying on it is not a "we will get to it" risk — it is a hard ceiling on what you can configure.

If you are mid-migration from gemini-3-flash-preview already, do the SDK swap and the thinking_level/thinking_budget config change in the same pass — see /migrate for the full checklist. Doing one without the other just trades one silent failure mode for another.