Skip to content

fix(vertex): resolve project_id from credentials before building request URL#1742

Open
sean-kim05 wants to merge 1 commit into
anthropics:mainfrom
sean-kim05:fix/vertex-resolve-project-id-from-adc
Open

fix(vertex): resolve project_id from credentials before building request URL#1742
sean-kim05 wants to merge 1 commit into
anthropics:mainfrom
sean-kim05:fix/vertex-resolve-project-id-from-adc

Conversation

@sean-kim05

Copy link
Copy Markdown

Summary

AnthropicVertex / AsyncAnthropicVertex fail on every request with

RuntimeError: No project_id was given and it could not be resolved from credentials. ...

whenever the project is meant to be resolved from Application Default Credentials rather than passed explicitly or set via ANTHROPIC_VERTEX_PROJECT_ID.

Root cause

The request URL is built in _prepare_options, which needs a project_id:

def _prepare_options(self, options):
    return _prepare_options(options, project_id=self.project_id, region=self.region)
    # -> raises "could not be resolved from credentials" when project_id is None

Resolution from ADC only happens inside _ensure_access_token (load_auth() returns (credentials, project_id) from google.auth.default()), which the base client calls from _prepare_request. But the base client runs them in this order:

options = self._prepare_options(options)   # builds URL, needs project_id  ← runs first, raises
request = self._build_request(options, ...)
self._prepare_request(request)             # loads credentials, resolves project_id  ← never reached

So the ADC project is never consulted before the URL is built — the error message ("could not be resolved from credentials") is emitted without the credentials ever being loaded. This breaks the common deployment pattern of running on GCE/GKE/Cloud Run with ADC and no explicit project.

Fix

Resolve credentials in _prepare_options when project_id is unset, so the ADC project is available before the URL is built. _ensure_access_token caches the loaded credentials, so the subsequent _prepare_request call reuses them without a second network round-trip. Applied symmetrically to the sync and async clients.

When project_id genuinely can't be resolved (e.g. an access_token was supplied without a project, or ADC has no default project), the same RuntimeError is still raised — now after credentials were actually consulted.

Testing

Added test_project_id_resolved_from_credentials (sync + async) in tests/lib/test_vertex.py: with no explicit project_id and no env var, a mocked load_auth supplies the project, and the request is asserted to hit /projects/adc-project/.../rawPredict.

Verified RED (RuntimeError before the fix) → GREEN. Full tests/lib/test_vertex.py passes (26 tests); ./scripts/lint clean (ruff + pyright + mypy).

…est URL

The Vertex client builds its request URL in `_prepare_options`, which requires
a project_id. When one isn't passed explicitly or set via
`ANTHROPIC_VERTEX_PROJECT_ID`, it is meant to be resolved from Application
Default Credentials — but that resolution only happens in
`_ensure_access_token`, which the base client calls from `_prepare_request`,
*after* `_prepare_options`. So a client relying on ADC for its project (the
common case on GCE/GKE/Cloud Run) failed on every request with "No project_id
was given and it could not be resolved from credentials" without ever
consulting the credentials.

Resolve credentials in `_prepare_options` when project_id is unset, so the ADC
project is available before the URL is built. `_ensure_access_token` caches, so
the subsequent `_prepare_request` call reuses the loaded credentials without a
second network round-trip. Fixed on both the sync and async clients.
@sean-kim05
sean-kim05 requested a review from a team as a code owner July 7, 2026 04:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant