GEMINI LABJP
DEADLINE — gemini-robotics-er-1.6-preview shut down yesterday, August 31. If code started erroring today, this retirement is the first thing to checkNEXT — The next deadline is September 30, when the gemini-omni-flash-preview endpoint is retired. The migration target is gemini-omni-1.1-flash, GA since August 27APIKEY — The Gemini API begins rejecting requests from standard API keys during September. If you have not moved to auth keys yet, this month is the real deadlineSHEETS — Sheets canvas, a Gemini-powered feature, began a gradual rollout to Scheduled Release domains on August 31, with up to 15 days before it becomes visibleMEET — Starting August 31, Google Meet hardware touch controllers can start, stop, and manage the Take notes for me feature directly from the in-room screenPARAMS — temperature, top_p, and top_k remain silently deprecated: requests are accepted and the values ignored. Code that assumes determinism needs to be verified by measurementDEADLINE — gemini-robotics-er-1.6-preview shut down yesterday, August 31. If code started erroring today, this retirement is the first thing to checkNEXT — The next deadline is September 30, when the gemini-omni-flash-preview endpoint is retired. The migration target is gemini-omni-1.1-flash, GA since August 27APIKEY — The Gemini API begins rejecting requests from standard API keys during September. If you have not moved to auth keys yet, this month is the real deadlineSHEETS — Sheets canvas, a Gemini-powered feature, began a gradual rollout to Scheduled Release domains on August 31, with up to 15 days before it becomes visibleMEET — Starting August 31, Google Meet hardware touch controllers can start, stop, and manage the Take notes for me feature directly from the in-room screenPARAMS — temperature, top_p, and top_k remain silently deprecated: requests are accepted and the values ignored. Code that assumes determinism needs to be verified by measurement
Articles/API / SDK
API / SDK/2026-09-01Advanced

Your New Gemini API Key Never Took Effect, and Load Order Wasn't the Reason

When several sources supply the same environment variable, swapping your key can leave the old value in place. Here is what four load orders actually produced, and a ledger that records which source won.

Gemini API229API keys2environment variablesmigration9operations17

Premium Article

September arrived, and with it the one item in my Gemini code that has to be finished this month: moving from standard API keys to auth keys. The clearest place to start was the wallpaper category classification batch I run as an indie developer, so I started there.

I rewrote the value in .env to the new key, ran the job locally once, confirmed a response came back, and put it back on its schedule. The next morning's log showed requests still going out with the old key.

The .env file had definitely changed. The process was definitely reading that file. The old value was being used anyway.

Three Sources Were Fighting Over One Name

Before hunting for a cause, I listed every place that hands GEMINI_API_KEY to that process. There were three.

Supply pathWhere it livesFindable by code search?
Shell environmentAn export in the scheduler's wrapper scriptYes, but in a different repo
dotenv file.env at the project rootFilename yes, value no
Secret fileJSON placed at deploy timeNo

This is where the first mistake happens. Running grep -rn "GEMINI_API_KEY" surfaces the places that read the value: the os.environ.get(...) and process.env.... lines. The places that write it live in CI settings screens, files expanded at deploy time, and wrapper scripts, which sit either outside the repository or in a corner of it.

Count only the readers and you conclude "three reads, three fixes." The entire supply-side inventory falls out of scope. I got that order wrong once.

Four Load Orders, Same Winner

My first suspicion was load order. If the last read wins, I reasoned, I just need the new key read last. It is a reasonable guess.

So I wrote the smallest possible loader with three supply paths, and ran it with the order shuffled.

# probe.py — a config loader with three supply paths; shuffle the order, watch the winner
import os, sys, json
from dotenv import load_dotenv
 
def from_shell():
    # only reads what is already in the process; writes nothing
    return os.environ.get("GEMINI_API_KEY")
 
def from_dotenv():
    # python-dotenv defaults to override=False: it will not write over an existing value
    load_dotenv("/tmp/keyaudit/.env")
    return os.environ.get("GEMINI_API_KEY")
 
def from_secretfile():
    # a plain assignment; overwrites unconditionally
    d = json.load(open("/tmp/keyaudit/secrets.json"))
    os.environ["GEMINI_API_KEY"] = d["GEMINI_API_KEY"]
    return os.environ["GEMINI_API_KEY"]
 
fns = {"shell": from_shell, "dotenv": from_dotenv, "secretfile": from_secretfile}
for name in sys.argv[1].split(","):
    fns[name]()
 
print(f"order={sys.argv[1]:32s} winner={os.environ.get('GEMINI_API_KEY')}")

With the new key in .env, the old key in the secret file, and the old key in the shell, I tried four orders:

order=shell,dotenv,secretfile          winner=OLD_STANDARD_KEY_from_secretfile
order=shell,secretfile,dotenv          winner=OLD_STANDARD_KEY_from_secretfile
order=dotenv,secretfile,shell          winner=OLD_STANDARD_KEY_from_secretfile
order=secretfile,dotenv,shell          winner=OLD_STANDARD_KEY_from_secretfile

All four produced the same winner: the secret file holding the old key. Rearranging the sequence moved nothing.

The reason is that each path has its own policy toward an existing value. load_dotenv() respects what is already there and declines to write. A plain os.environ[...] = value overwrites without looking. So the outcome is not decided by who reads last. It is decided by this: if any path grants itself permission to overwrite, that path becomes the final winner.

Until those four lines printed, I had been shuffling import statements. While you believe the cause is ordering, no amount of reordering changes the symptom, so you gather no new information.

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
You will be able to tell, before you start a key migration, which of your supply paths are allowed to overwrite and which ones fail silently
You will be able to drop a ledger into your own runtime that records which key actually reached the request, without ever writing the key value to a log
You will be able to explain why shuffling four different load orders changed nothing, and skip the detour of rearranging import statements to fix it
Secure payment via Stripe · Cancel anytime

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Gemini Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $15 for lifetime access
View Membership →

Related Articles

API / SDK2026-08-01
When Sampling Parameters Were Deprecated, Diversity Broke Before Determinism Did
Deprecating temperature, top_p and top_k hurt the diversity-generating side of my pipeline, not the deterministic side. Counting real call sites, moving diversity to the input layer, and measuring effective diversity.
API / SDK2026-07-06
When Context Caching Didn't Lower My Gemini Bill — Field Notes on Measuring the Real Hit Rate
When Context Caching is enabled but the Gemini API bill barely drops, this field note measures the real hit rate from usage_metadata, separates TTL churn from fragmentation, and walks through a staged recovery.
API / SDK2026-07-01
Keeping Unattended Jobs From Failing Silently: A Preflight Gate for Gemini's Platform Changes
Unrestricted API keys are now rejected, the old CLI reached end of life, and the Interactions API is becoming the default entry point. These 2026 platform shifts stop working automation without raising an error. Here is a preflight gate, with runnable code, that catches the failure before the batch runs.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →