fix: re-read Gemini env vars in lazy client build

`_normalize_gemini_fields` captures `GOOGLE_API_KEY` / `GEMINI_API_KEY`
/ `GOOGLE_CLOUD_PROJECT` at construction time, so an LLM constructed
before deployment env vars are set would freeze `self.api_key = None`
and the lazy `_get_sync_client` build would then always auth-fail.

Re-read the env vars inside `_get_sync_client` when `self._client` is
None and the corresponding field is still unset, matching the pattern
used for the other native providers.

Add a regression test that constructs `GeminiCompletion` with no env
vars set, patches them in afterwards, and asserts the lazy build
succeeds and writes the resolved key back onto the LLM.
This commit is contained in:
Greyson LaLonde
2026-04-12 05:03:51 +08:00
parent 60e8a4a364
commit 41403c09b4
2 changed files with 25 additions and 0 deletions

View File

@@ -130,6 +130,14 @@ class GeminiCompletion(BaseLLM):
def _get_sync_client(self) -> Any:
if self._client is None:
# Re-read env vars so a deferred build can pick up credentials
# that weren't set at instantiation time.
if not self.api_key:
self.api_key = os.getenv("GOOGLE_API_KEY") or os.getenv(
"GEMINI_API_KEY"
)
if not self.project:
self.project = os.getenv("GOOGLE_CLOUD_PROJECT")
self._client = self._initialize_client(self.use_vertexai)
return self._client

View File

@@ -64,6 +64,23 @@ def test_gemini_completion_module_is_imported():
assert hasattr(completion_mod, 'GeminiCompletion')
def test_gemini_lazy_build_reads_env_vars_set_after_construction():
"""When `LLM(model="gemini/...")` is constructed before env vars are set,
the lazy client builder must re-read `GOOGLE_API_KEY` / `GEMINI_API_KEY`
so the LLM works once credentials become available."""
from crewai.llms.providers.gemini.completion import GeminiCompletion
with patch.dict(os.environ, {}, clear=True):
llm = GeminiCompletion(model="gemini-1.5-pro")
assert llm.api_key is None
assert llm._client is None
with patch.dict(os.environ, {"GEMINI_API_KEY": "late-key"}, clear=True):
client = llm._get_sync_client()
assert client is not None
assert llm.api_key == "late-key"
def test_native_gemini_raises_error_when_initialization_fails():
"""
Test that LLM raises ImportError when native Gemini completion fails.