# 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.

By Tahir Nazir · Published 2026-09-10 · Updated 2026-09-10
Canonical: https://www.its-tahir.com/blog/claude-code-vertex-ai-model-not-found

`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. (Not on Google Cloud, and seeing "There's an issue with the selected model" instead? That's [a 404 with its own set of causes](/blog/claude-code-issue-with-the-selected-model).)

## 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 when `GCLOUD_PROJECT`, `GOOGLE_CLOUD_PROJECT`, or the credential file referenced by `GOOGLE_APPLICATION_CREDENTIALS` carries 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.

```bash
echo $ANTHROPIC_VERTEX_PROJECT_ID
```

Then 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:

```bash
export CLOUD_ML_REGION=global          # global endpoint
export CLOUD_ML_REGION=us              # multi-region
export CLOUD_ML_REGION=us-east5        # specific region
```

The 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 a client's data-residency rules decide the region for you, check this before you commit — the same goes for [the new in-country cloud regions announced for Saudi Arabia](/blog/leap-2026-riyadh-developer-takeaways), which open with a subset of services.

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:

```bash
export VERTEX_REGION_CLAUDE_HAIKU_4_5=us-east5
export VERTEX_REGION_CLAUDE_4_6_SONNET=europe-west1
```

Most 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:

```bash
export ANTHROPIC_MODEL='claude-sonnet-5'
```

Two rules that catch people out:

- **Aliases are not pins.** `opus` and `sonnet` don't pin anything, and neither does a model ID Claude Code doesn't recognize.
- **Pinning Opus alone changes Sonnet too.** Setting `ANTHROPIC_DEFAULT_OPUS_MODEL` without `ANTHROPIC_DEFAULT_SONNET_MODEL` counts 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:

```bash
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:

```bash
/setup-vertex
```

Manual Vertex AI configuration is still the right call for CI or a scripted enterprise rollout. The minimum is:

```bash
export CLAUDE_CODE_USE_VERTEX=1
export CLOUD_ML_REGION=global
export ANTHROPIC_VERTEX_PROJECT_ID=YOUR-PROJECT-ID
```

Plus `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:

```json
{
  "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

1. **Which project?** `ANTHROPIC_VERTEX_PROJECT_ID` overrides your credentials. Check it first.
2. **Which region resolved?** Compare `/status` against what you exported — a malformed value is silently discarded and falls back to `us-east5`.
3. **Is the model enabled in Vertex AI Model Garden**, for *that* project, and available on *that* endpoint type?
4. **Getting 429s?** Check the small/fast model is supported in your region, not just the primary.
5. **Behaviour differs between machines?** Something is falling back at startup. Pin versions.
6. **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.

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 none of these match, [every Claude Code error and its fix](/blog/claude-code-troubleshooting) lists the other failures by their exact message.

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](/blog/claude-code-ssl-certificate-corporate-proxy). And for the transient capacity failures that look like configuration problems but aren't, [529 overloaded and what gets retried](/blog/claude-code-529-overloaded-retry-behaviour) covers where the retry boundary sits. Building on top of these platforms is the work [ContextZero](/work/contextzero) came out of.

## FAQ

### 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.

## Sources

- [Claude Code on Google Cloud's Agent Platform — Claude Code docs](https://code.claude.com/docs/en/google-vertex-ai)
- [Environment variables reference — Claude Code docs](https://code.claude.com/docs/en/env-vars)
- [Model configuration — Claude Code docs](https://code.claude.com/docs/en/model-config)
