Two days left before the August 17 shutdown.
I ran the script that generates header images for my blog posts, just to see where things stood. It finished without complaint. Not a single warning.
Two days from a hard cutoff, and everything looked fine. That silence bothered me enough to open up google-genai and read it.
The SDK does say something. It just isn't talking about August 17.
The deadline the SDK tells you about is 2027, not this weekend
First question: does the latest release still have generate_images?
pip index versions google-genai
# google-genai (2.18.1)
# Available versions: 2.18.1, 2.18.0, 2.17.0, ...
# INSTALLED: 2.18.1
# LATEST: 2.18.1from google.genai import models
print(hasattr(models.Models, "generate_images"))
# TrueVersion 2.18.1 is the newest release as of August 15, 2026, and the method is right there. So "I upgraded the SDK, so I must have migrated" falls apart immediately.
That doesn't mean the SDK is silent. The method carries a deprecation notice on a decorator:
import inspect
from google.genai import models
src = inspect.getsource(models.Models.generate_images)
print(src[:400])Here is the full text of that notice:
The generate_images method is deprecated and will be removed in the next
major release (not before Jan. 1 2027). Please use the generate_content
method with image models instead.Removed in the next major release, and not before January 1, 2027.
The deadline the SDK owns is more than a year out. It says nothing at all about August 17. Read that notice, feel reassured, and you walk straight into the weekend.
What shuts down is the model, not the method
Laid out side by side, there is more than one deadline, and different parties control them.
| What ends | When | Who controls it | Verifiable locally? |
|---|---|---|---|
Removal of generate_images |
Next major release (not before Jan 1, 2027) | Your SDK version | Yes |
| Shutdown of the three imagen-4.0 models | August 17 | Server side | No |
| Shutdown of the Gemini 3 Image models | August 17 | Server side | No |
Working as an indie developer, with nobody else running these scripts, "it ran today" quietly becomes my entire verification step. Columns three and four are where I had been fooling myself. A script that runs clean today tells you nothing about whether the model is alive tomorrow. The confidence you get from a successful local run stops at the SDK boundary.
The thing that stops is not the method. It is the model ID you hand to that method. If you haven't inventoried your call sites yet, Getting Ready for the August 17 Gemini Image Model Shutdown walks through that first.
The warning fires once per process, and you can't get it back
Something else surfaced once I actually ran the call.
That deprecation warning appears exactly once per process. Turning the warning filters up to maximum does not bring it back.
import warnings
from google import genai
client = genai.Client(api_key="YOUR_API_KEY")
for n in (1, 2):
with warnings.catch_warnings(record=True) as caught:
warnings.simplefilter("always")
try:
client.models.generate_images(
model="imagen-4.0-generate-001",
prompt="a quiet morning street",
)
except Exception as e:
err = type(e).__name__
print(f"call#{n}: warnings={len(caught)} err={err}")What I got:
call#1: warnings=1 err=ClientError
call#2: warnings=0 err=ClientErrorZero on the second call, with simplefilter("always") in effect. The SDK keeps its own flag that says "emitted once, never again," and no filter setting on your side overrides it.
The warning category is worth a look too:
from google.genai import _common
print([c.__name__ for c in _common.ExperimentalWarning.__mro__])
# ['ExperimentalWarning', 'Warning', 'Exception', 'BaseException', 'object']It sits directly under Warning, not under DeprecationWarning. If you have tooling that watches for DeprecationWarning to catch exactly this class of problem, this notice slips right past it.
For a long-running worker, or a batch job that starts in the morning and runs all day, missing that one line at startup means you will not see it again that day. Which may well be why my own script looked so calm. It had already said its piece, hours earlier, to nobody.
If you want to keep it, catch it at startup and push it into your logs:
import logging
import warnings
logging.captureWarnings(True)
warnings.simplefilter("always")logging.captureWarnings(True) routes warnings through the py.warnings logger. Even when nobody is watching stderr, the message lands somewhere durable.
Errors before the network and errors after it are different problems
While migrating, you will hit failures that look alike but come from very different layers. These are the ones I actually ran into.
1. No API key
ValueError: No API key was provided. Please pass a valid API key.This stops at client construction. Nothing left your machine.
2. An argument in the wrong place
from google.genai import types
types.GenerateContentConfig(aspect_ratio="9:16")pydantic_core._pydantic_core.ValidationError: 1 validation error for
GenerateContentConfig
aspect_ratio
Extra inputs are not permitted [type=extra_forbidden, ...]Also pre-network. aspect_ratio doesn't live on GenerateContentConfig; it belongs to ImageConfig. The current ImageConfig accepts seven fields: aspect_ratio, image_size, output_mime_type, output_compression_quality, person_generation, prominent_people, and image_output_options. For the full mapping of where every old argument lands, see Rewriting generate_images as generate_content, where the arguments actually go.
3. An invalid key
ClientError: 400 INVALID_ARGUMENT.
{'error': {'code': 400, 'message': 'API key not valid. ...',
'status': 'INVALID_ARGUMENT'}}Now you are looking at a server response. A ClientError means the request reached the API.
4. A retired model
I can't show you this one. It isn't reproducible until August 17 has passed, so I'd rather say so plainly than invent a sample. Structurally it belongs with case three: a server-side response, not a local mistake.
A rule of thumb that keeps these straight: ValueError and ValidationError are about how you wrote your code, while anything from ClientError onward is about the state on the other end. For a wider tour of image generation failures, Five Errors You'll Hit with Gemini Image Generation covers more ground.
Three decisions worth making before the 17th
Two days doesn't leave room for much. In priority order:
- Count your model IDs, not your method calls. Grep for the string
imagen-4.0, not forgenerate_images. The method stays; the model is what disappears. - Decide now what breaks on the 18th. When image generation fails, does the whole job stop, or does it skip the image and carry on? Making that call under pressure, on the day, is the expensive version.
- Stop throwing warnings away. Two lines of
logging.captureWarnings(True)setup. It won't just help here — it buys you weeks of lead time on the next deprecation.
I had been treating the SDK's silence as evidence that I was fine. What I could verify locally was only ever my own code; the deadline was always held by the other side. Obvious in hindsight, and worth the twenty minutes it took to confirm by hand.
If you're standing in the same spot, I hope this saves you a little of that time.