A region wall, not a code bug
The pattern is so consistent it deserves a name: everything passes on your laptop, then the first request from a fresh VPS or cloud box dies with a 400. Free-tier availability depends on the country the request comes from, and a datacenter in Frankfurt or Singapore isn't the desk you tested at. The API rejects the call before processing a single token; the precondition check runs first. Enabling billing removes the wall, because the paid tier doesn't carry the free tier's regional restrictions.
What it looks like
A representative response body, in Google's standard envelope where the numeric code mirrors the HTTP status and status carries the gRPC name:
{
"error": {
"code": 400,
"message": "User location is not supported for the API use without a billing account linked.",
"status": "FAILED_PRECONDITION"
}
}
Phrasing varies by setup, so key your handling off the status string, not the sentence.
Three checks, in order
First: where does the server run? Not where you bought it, where the datacenter sits. Hosting dashboards bury this; your provider's region setting is the truth. Second: is billing linked? Open the project in Google AI Studio and check, don't assume. Third: is the key from the project you think it is? Stale environment variables point at unbilled sandbox projects more often than anyone admits, and the fix you applied to the right project does nothing for the wrong key.
After billing: budget like an adult
Once billing is on, the free tier goes back to its real job — testing, not production traffic. Set budget alerts the same day, sized to a number that would make you look twice. Then price the workload honestly: Gemini 3.5 Flash at $1.50 in and $9.00 out per million tokens keeps modest products in pocket-change territory, and knowing that number beats fearing it. If your project truly belongs on a $0 budget, the no-subscription guide covers who can stay free without hitting walls like this one.