openclaw - 💡(How to fix) Fix Google Gemini chat model routes to openai-responses transport (401), native @google/genai transport never selected

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

Chat completions for a google/* model are dispatched through the openai-responses transport instead of the native Google (@google/genai) transport. The Gemini API key is then sent as a Bearer token to OpenAI's /responses endpoint, which (correctly) rejects it with a 401. The native Google transport is never reached.

This makes it impossible to use a Google Gemini model as a chat model (heartbeat, subagent, or main) even though:

  • the key is valid (direct curl to generativelanguage.googleapis.com returns HTTP 200), and
  • the model resolves and shows configured in openclaw models list.

Error Message

[openai-transport] [responses] error provider=google api=openai-responses model=flash-lite name=Error status=401 code=invalid_api_key type=invalid_request_error

Root Cause

Chat completions for a google/* model are dispatched through the openai-responses transport instead of the native Google (@google/genai) transport. The Gemini API key is then sent as a Bearer token to OpenAI's /responses endpoint, which (correctly) rejects it with a 401. The native Google transport is never reached.

This makes it impossible to use a Google Gemini model as a chat model (heartbeat, subagent, or main) even though:

  • the key is valid (direct curl to generativelanguage.googleapis.com returns HTTP 200), and
  • the model resolves and shows configured in openclaw models list.

Fix Action

Fix / Workaround

Chat completions for a google/* model are dispatched through the openai-responses transport instead of the native Google (@google/genai) transport. The Gemini API key is then sent as a Bearer token to OpenAI's /responses endpoint, which (correctly) rejects it with a 401. The native Google transport is never reached.

Code Example

[openai-transport] [responses] error provider=google api=openai-responses model=flash-lite
  name=Error status=401 code=invalid_api_key type=invalid_request_error
  message=401 Incorrect API key provided: AQ.Ab8RN*****3eAw.
  You can find your API key at https://platform.openai.com/account/api-keys.
[model-fallback/decision] decision=candidate_failed requested=google/gemini-2.5-flash-lite
  candidate=google/flash-lite reason=auth next=none

---

curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash-lite:generateContent?key=AQ.…" \
  -H "Content-Type: application/json" \
  -d '{"contents":[{"parts":[{"text":"say ok"}]}]}'
# → HTTP 200, {"candidates":[{"content":{"parts":[{"text":"OK"}]
RAW_BUFFERClick to expand / collapse

Summary

Chat completions for a google/* model are dispatched through the openai-responses transport instead of the native Google (@google/genai) transport. The Gemini API key is then sent as a Bearer token to OpenAI's /responses endpoint, which (correctly) rejects it with a 401. The native Google transport is never reached.

This makes it impossible to use a Google Gemini model as a chat model (heartbeat, subagent, or main) even though:

  • the key is valid (direct curl to generativelanguage.googleapis.com returns HTTP 200), and
  • the model resolves and shows configured in openclaw models list.

Environment

  • OpenClaw 2026.5.28 (e932160) — also reproduced on 2026.5.27 (27ae826)
  • Linux x64, Node v22.22.2, headless VPS
  • Google provider plugin @openclaw/google-provider (stock) enabled
  • Auth: Google AI Studio API key in the new AQ. format (not the legacy AIza… format)

Observed log

[openai-transport] [responses] error provider=google api=openai-responses model=flash-lite
  name=Error status=401 code=invalid_api_key type=invalid_request_error
  message=401 Incorrect API key provided: AQ.Ab8RN*****3eAw.
  You can find your API key at https://platform.openai.com/account/api-keys.
[model-fallback/decision] decision=candidate_failed requested=google/gemini-2.5-flash-lite
  candidate=google/flash-lite reason=auth next=none

Note provider=google api=openai-responses — the provider is correctly identified as google, but the transport selected is openai-responses.

Reproduction

  1. Configure a Google Gemini chat model, e.g. google/gemini-2.5-flash-lite, set as agents.defaults.heartbeat.model (or spawn a subagent with --model google/gemini-2.5-flash-lite).
  2. Provide a Google AI Studio key in the new AQ. format via GEMINI_API_KEY env var.
  3. Trigger any chat completion on that model.
  4. Request is routed to OpenAI /responses with the Gemini key → 401.

What I ruled out (none fixed it)

  • GEMINI_API_KEY and GOOGLE_API_KEY env vars (both present, gateway env verified).
  • auth.profiles."google:default" = { provider: "google", mode: "api_key" } in openclaw.json.
  • Inline credential in agent auth-profiles.json: { type: "api_key", provider: "google", key: "AQ.…" } — identical structure to the working anthropic:default profile.
  • models.providers.google.models[] registration with canonical id gemini-2.5-flash-lite.
  • Removed all aliases; used only the canonical google/gemini-2.5-flash-lite.
  • Multiple full gateway restarts after each change.

Anthropic models work perfectly with the analogous inline auth-profiles.json entry, so the credential-resolution wiring is fine for anthropic but the transport selection for google falls back to openai-responses.

Suspected cause

The provider→transport resolver does not select the native @google/genai transport for the google provider (at least when the key is in the new AQ. AI Studio format), and falls through to the generic openai-responses default. The key-format detection (legacy AIza… vs new AQ.…) is a likely trigger.

Direct-key sanity check (proves key + endpoint are good)

curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash-lite:generateContent?key=AQ.…" \
  -H "Content-Type: application/json" \
  -d '{"contents":[{"parts":[{"text":"say ok"}]}]}'
# → HTTP 200, {"candidates":[{"content":{"parts":[{"text":"OK"}]…

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - 💡(How to fix) Fix Google Gemini chat model routes to openai-responses transport (401), native @google/genai transport never selected