Claude Code on Vertex AI: Why You Get 404s, Wrong Regions and an Opus-Sized Bill
Model not found on Google Cloud's Agent Platform is rarely one problem. A malformed region is silently ignored and falls back to us-east5, ANTHROPIC_VERTEX_PROJECT_ID overrides the project in your credentials, and a deployment with no pinned model is billed at the Opus rate.
model not found on Google Cloud's Agent Platform — still labelled Vertex AI in most places, including Claude Code's own login prompt — has four distinct causes, and the error text is identical for all of them. Working through them in order takes about five minutes; guessing takes an afternoon.
There's also a fifth problem that never produces a model not found error — or any error at all: a deployment that silently bills at the Opus rate. That one is at the bottom, and it's the one worth reading even if your setup already works.
Start here: which project are requests actually going to?
Before touching Model Garden, confirm the project. This is the single most misleading part of the setup:
Claude Code addresses Google Cloud's Agent Platform requests to the project in
ANTHROPIC_VERTEX_PROJECT_ID, even whenGCLOUD_PROJECT,GOOGLE_CLOUD_PROJECT, or the credential file referenced byGOOGLE_APPLICATION_CREDENTIALScarries a different project.
So you can authenticate correctly to Vertex AI, with a service account key for the right project, and still have every request land somewhere else. If you enabled Claude models in project A and ANTHROPIC_VERTEX_PROJECT_ID says project B, you get a 404 that looks exactly like "the model isn't enabled" — because in project B, it isn't.
echo $ANTHROPIC_VERTEX_PROJECT_IDThen check it against what /status reports. The GCP project, Default region and Model rows show what Claude Code actually resolved. If the API provider line is missing entirely, your environment variables never reached the process — they need to be exported in the shell that launched claude, or set in the env block of your settings file.
A malformed region is discarded silently
This one is genuinely nasty because nothing tells you.
If a region value isn't shaped like a region or location name, Claude Code treats it as unset. For example, Claude Code treats a value containing a slash, dot, or space as unset.
There's no error and no warning. The variable is simply dropped, and each one falls back to something else:
| Variable | Falls back to |
|---|---|
VERTEX_REGION_CLAUDE_* | CLOUD_ML_REGION |
CLOUD_ML_REGION | us-east5 |
So a trailing space, a copy-pasted us-east5/, or a stray newline in your .env means requests go to us-east5 — a region you never chose, which may not have your model enabled. You get model not found while staring at a config file that looks correct.
Check the resolved value in /status rather than trusting what you exported.
Global, multi-region, or a specific region
Claude Code supports all three endpoint types, and CLOUD_ML_REGION takes any of them:
export CLOUD_ML_REGION=global # global endpoint
export CLOUD_ML_REGION=us # multi-region
export CLOUD_ML_REGION=us-east5 # specific regionThe catch is that model availability on Vertex differs across all three. A model can be available on the global endpoint and not in your specific region, or vice versa. Model Garden shows this under Supported features.
If you're on global and a model doesn't support global endpoints, you have two options: pick a different model with ANTHROPIC_MODEL, or override the region for that model only:
export VERTEX_REGION_CLAUDE_HAIKU_4_5=us-east5
export VERTEX_REGION_CLAUDE_4_6_SONNET=europe-west1Most model versions have a corresponding VERTEX_REGION_CLAUDE_* variable.
A caveat on "just read the docs table": model availability is per-project as well as per-region. When I was wiring a content pipeline onto Vertex earlier this year, model IDs I'd taken straight from a current pricing page returned 404 in four different regions on my own project, while an older family worked everywhere. The table tells you what exists; only a request tells you what your Vertex project can invoke. Probe before you build on an assumption — a model not found here means "not for you, here, today", not "does not exist".
The 429 that's really a region problem
If you're getting rate-limited rather than 404ing, there's a specific cause worth checking before you request a quota increase:
For regional endpoints, ensure the primary model and small/fast model are supported in your selected region.
The small/fast model is easy to forget because you never chose it. Background work — session titles and similar — runs on it constantly. And on Agent Platform there's a wrinkle: Claude Code uses the default Sonnet model for background tasks rather than a Haiku-class model, because Haiku may not be enabled in every project or region.
So a region where your primary model works but the background model doesn't produces a steady trickle of failures from work you didn't initiate. Switching to CLOUD_ML_REGION=global generally improves availability.
Silent fallback at startup
When Claude Code starts with Agent Platform configured, it checks the models it intends to use are actually invokable.
If you haven't pinned anything and the current default is unavailable, it falls back for that session and shows a notice — trying earlier versions of the default first, and dropping from Opus to the default Sonnet if no Opus version is available.
The fallback is not persisted. So you get a session on a different model than you think, every time, until you either enable the newer model in Model Garden or pin a version. If a colleague reports different behaviour on the same config, or a model not found appears only on some machines, this is a strong candidate.
The expensive one: unpinned means Opus
This produces no error, which is exactly why it's worth knowing.
When nothing is pinned, the primary model on Agent Platform defaults to claude-opus-5. And:
Opus models have a higher per-token price than Sonnet models, so a deployment that doesn't pin a primary model is billed at the Opus rate once it updates to v2.1.207 or later.
A rollout that worked fine for months can quietly change price on an update. To keep Sonnet as primary, pin it with a full model ID:
export ANTHROPIC_MODEL='claude-sonnet-5'Two rules that catch people out:
- Aliases are not pins.
opusandsonnetdon't pin anything, and neither does a model ID Claude Code doesn't recognize. - Pinning Opus alone changes Sonnet too. Setting
ANTHROPIC_DEFAULT_OPUS_MODELwithoutANTHROPIC_DEFAULT_SONNET_MODELcounts as a selection, because the built-in Sonnet model may not be enabled in a project that steers its own Opus.
For a team rollout, pin all three:
export ANTHROPIC_DEFAULT_OPUS_MODEL='claude-opus-4-8'
export ANTHROPIC_DEFAULT_SONNET_MODEL='claude-sonnet-5'
export ANTHROPIC_DEFAULT_HAIKU_MODEL='claude-haiku-4-5@20251001'Pinning also decides when your users move to a new model, rather than a Claude Code release deciding for them.
The setup you probably want
If you're configuring this by hand, don't. Run claude, choose 3rd-party platform → Google Vertex AI, and the wizard detects your project and region, verifies which Claude models your project can actually invoke, and lets you pin them — writing the result to the env block of your user settings.
That verification step is the whole ballgame: it answers the availability question empirically instead of making you infer it from a 404.
Reopen it any time with:
/setup-vertexManual Vertex AI configuration is still the right call for CI or a scripted enterprise rollout. The minimum is:
export CLAUDE_CODE_USE_VERTEX=1
export CLOUD_ML_REGION=global
export ANTHROPIC_VERTEX_PROJECT_ID=YOUR-PROJECT-IDPlus roles/aiplatform.user on the account — which carries aiplatform.endpoints.predict, required for both model invocation and token counting. And note Model Garden access requests may take 24–48 hours to approve, so a 404 on a brand-new project may just be a pending request.
Credentials that expire mid-session
If you authenticate with Application Default Credentials, gcpAuthRefresh re-authenticates rather than failing:
{
"gcpAuthRefresh": "gcloud auth application-default login",
"env": {
"ANTHROPIC_VERTEX_PROJECT_ID": "your-project-id"
}
}Claude Code first requests a token with your current credentials to confirm they're genuinely expired, and skips the command if they still work. If that check doesn't finish within five seconds it skips the command too, running it only after a request actually fails. The refresh command times out after three minutes.
Worth knowing before you put this in project settings: it runs under the same workspace-trust rule as hooks, which includes -p sessions in folders you've never trusted.
Triage order
- Which project?
ANTHROPIC_VERTEX_PROJECT_IDoverrides your credentials. Check it first. - Which region resolved? Compare
/statusagainst what you exported — a malformed value is silently discarded and falls back tous-east5. - Is the model enabled in Vertex AI Model Garden, for that project, and available on that endpoint type?
- Getting 429s? Check the small/fast model is supported in your region, not just the primary.
- Behaviour differs between machines? Something is falling back at startup. Pin versions.
- Never pinned a primary model? You're on Opus rates. Fix that today.
Key takeaways
- ANTHROPIC_VERTEX_PROJECT_ID overrides GCLOUD_PROJECT, GOOGLE_CLOUD_PROJECT and the project inside your credential file — so a 404 is often the wrong project, not a disabled model.
- A region value containing a slash, dot or space is treated as unset with no error. CLOUD_ML_REGION then falls back to us-east5.
- Without a pinned primary model, deployments are billed at the Opus rate from v2.1.207 onward. Aliases like 'opus' do not count as pins.
- 429s on a regional endpoint often trace to the small/fast background model being unsupported there, not the model you chose.
- The /setup-vertex wizard verifies which models your project can actually invoke — faster and more reliable than inferring availability from a 404.
Frequently asked questions
Why does Claude Code use a different GCP project than my credentials?
Because ANTHROPIC_VERTEX_PROJECT_ID wins. Claude Code addresses Agent Platform requests to the project named in that variable even when GCLOUD_PROJECT, GOOGLE_CLOUD_PROJECT, or the credential file referenced by GOOGLE_APPLICATION_CREDENTIALS carries a different project. If your models are enabled in one project and requests keep 404ing, check that variable before you check Model Garden.
Why did my region setting get ignored?
If a region value is not shaped like a region or location name, Claude Code treats it as unset rather than erroring. A value containing a slash, dot or space is discarded. VERTEX_REGION_CLAUDE_* then falls back to CLOUD_ML_REGION, and CLOUD_ML_REGION itself falls back to us-east5 — so a typo silently sends every request to a region you never chose.
Why is my Vertex deployment suddenly billed at Opus rates?
Because the primary model defaults to claude-opus-5 when nothing is pinned. Opus has a higher per-token price than Sonnet, so a deployment that never pinned a primary model is billed at the Opus rate once it updates to v2.1.207 or later. Set ANTHROPIC_MODEL to a full Sonnet model ID to keep Sonnet as primary.
Does setting a model alias like opus count as pinning?
No. Model aliases do not act as pins, and neither does a model ID Claude Code does not recognize. Pin a specific version with ANTHROPIC_DEFAULT_OPUS_MODEL, ANTHROPIC_DEFAULT_SONNET_MODEL or ANTHROPIC_MODEL using a full Agent Platform model ID.
The pattern across all of these: Vertex AI fails quietly. A wrong project, a malformed region and an unpinned model all produce either a generic model not found or no signal whatsoever. /status showing what actually resolved is worth more than any amount of re-reading your own config.
If your requests aren't reaching Google at all — TLS errors behind a corporate proxy rather than 404s from the API — that's a different layer entirely: why NODE_EXTRA_CA_CERTS isn't the fix. And for the transient capacity failures that look like configuration problems but aren't, 529 overloaded and what gets retried covers where the retry boundary sits. Building on top of these platforms is the work ContextZero came out of.
References
- Claude Code on Google Cloud's Agent Platform — Claude Code docscode.claude.com · accessed 2026-09-10
- Environment variables reference — Claude Code docscode.claude.com · accessed 2026-09-10
- Model configuration — Claude Code docscode.claude.com · accessed 2026-09-10
Last reviewed September 10, 2026
Tahir Nazir
Senior AI Engineer & Full-Stack Lead
5+ years shipping AI-powered products — RAG pipelines, agentic workflows, and MCP tooling. Top Rated on Upwork with a 100% job success score.
More about Tahir →Keep reading
New posts land here first. Follow along by RSS, or get in touch if you are building something similar.
Related articles
Claude Code Behind a Corporate Proxy: Why NODE_EXTRA_CA_CERTS Isn't the Fix
Unable to get local issuer certificate behind Zscaler or any TLS-inspecting proxy. Claude Code already trusts your OS certificate store by default — so the usual advice fixes it for some people and not others. The variable that actually decides is CLAUDE_CODE_CERT_STORE, and whether your runtime can read the OS store at all.TroubleshootingAI Engineering10 min readClaude Code 529 Overloaded: What It Retries For You, and What It Won't
A 529 isn't your usage limit and doesn't touch your quota. Claude Code already retried ten times before it told you. The useful question is which failures it retries automatically, which it deliberately doesn't, and the one environment variable that stops an unattended run dying on a transient capacity blip.TroubleshootingAI Engineering8 min readClaude Code Won't Start on Windows? Match the Error, Not the Guide
Raw mode is not supported, 'claude' is not recognized, 32-bit Windows, Exec format error on WSL1 — five different Windows startup failures that get treated as one problem. Each has a distinct cause and a distinct fix, and four of them aren't install failures at all.TroubleshootingAI Engineering8 min read