ITADN

Google Vertex authentication flow fails upon finding GOOGLE_API_KEY env var

#994Openthisisnic 创建于 2026-05-22
bug
T
thisisniccommented
Noticed this today when testing things on another PR. ``` r library(ellmer) chat <- chat_google_vertex( location = Sys.getenv("GOOGLE_CLOUD_LOCATION"), project_id = Sys.getenv("GOOGLE_CLOUD_PROJECT"), model = "gemini-3.1-flash-lite-preview", params = params(reasoning_tokens = 1024) ) chat$chat("What's 2+2") #> Error in `req_perform_connection()`: #> ! HTTP 401 Unauthorized. #> • OAuth error #> • realm: https://accounts.google.com/ #> ℹ API keys are not supported by this API. Expected OAuth2 access token or other #> authentication credentials that assert a principal. See #> https://cloud.google.com/docs/authentication Sys.unsetenv("GOOGLE_API_KEY") chat <- chat_google_vertex( location = Sys.getenv("GOOGLE_CLOUD_LOCATION"), project_id = Sys.getenv("GOOGLE_CLOUD_PROJECT"), model = "gemini-3.1-flash-lite-preview", params = params(reasoning_tokens = 1024) ) #> Warning: Unable to refresh token: invalid_grant #> reauth related error (invalid_rapt) #> https://support.google.com/a/answer/9368756 chat$chat("What's 2+2") #> Error in `if (expiry < Sys.time()) ...`: #> ! argument is of length zero ``` <sup>Created on 2026-05-22 with [reprex v2.1.1](https://reprex.tidyverse.org)</sup> *Issue 1 - checking for API key existence* Firstly, `default_google_credentials()` checks `GOOGLE_API_KEY` regardless of variant, and so when I have it set and call `chat_google_vertex()` it tries to send the API key even though I want 0Auth2. As `chat_google_vertex()` doesn't expose `credentials` or `api_key`, we can just skip this block in `default_google_credentials()`. (N.B. Google Vertex, which appears to be rebranded to Gemini Enterprise Agent Platform, [doesn't allow for using API keys except for in express mode](https://docs.cloud.google.com/gemini-enterprise-agent-platform/reference/express-mode/api-reference), which we don't implement here - there may be a case for doing so, but beyond the scope of this ticket) *Issue 2 - checking for API key existence* The second example actually was a workaround which did work, but failed when I switched IDEs and may have surfaced another bug. Claude description: > "After unsetting `GOOGLE_API_KEY`, `gargle::token_fetch()` tries to use cached credentials that need refreshing. The refresh fails with "invalid_grant", but gargle still returns the token (not NULL) in a bad state. Since token$can_refresh() is TRUE, we hit the final branch where expiry is computed from token$credentials$expires_in — but that's NULL after the failed refresh, so expiry becomes numeric(0). The subsequent `if (expiry < Sys.time())` then errors with "argument is of length zero". > The root cause is a stale gargle token cache, but ellmer should handle this more gracefully (e.g. defaulting expires_in to 0 when NULL, so it forces an immediate refresh attempt)" I'm thinking we want something like: ```r if (!is.null(token) && is.null(token$credentials$access_token)) { cli::cli_abort(c( "Google credentials were found but are not valid.", "i" = "Run {.code gcloud auth application-default login} to set up application default credentials." )) } ``` but without assuming the user is going to be using `gcloud` command line, so perhaps more generic. We might also want to check for the existence of `GOOGLE_CLOUD_LOCATION` and `GOOGLE_CLOUD_PROJECT` for `chat_google_vertex()`, or just set the default location/project param values to these env vars? In #434, it looks like the reason we don't have them as default is because there was nothing in the docs indicating this, but now there's https://docs.cloud.google.com/workflows/docs/reference/environment-variables
1 条评论