Google Generative AI 400 Error - All Models Failing Despite Valid API Key
OpenClaw returns generic 400 errors for all Google AI models while the same API key works via direct curl requests, indicating a request formatting or header injection issue in the OpenClaw Google provider.
π Symptoms
Primary Error Manifestation
All Google Generative AI models fail with identical, non-descriptive 400 errors regardless of model selection:
{
"error": "Google Generative AI API error (400)",
"rawErrorPreview": "Google Generative AI API error (400)",
"model": "gemini-2.5-flash",
"provider": "google"
}Verified Working Components
- API Key Validity: Direct
curlrequests succeed with identical API key - Auth Profile Configuration: Present and correctly structured
- Model Routing: Gateway confirms correct model selection
# Successful direct API call
$ curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent" \
-H 'Content-Type: application/json' \
-H 'X-goog-api-key: [REDACTED]' \
-X POST \
-d '{"contents":[{"parts":[{"text":"Say hi"}]}]}'
# Response: {"candidates":[{"content":{"parts":[{"text":"Hi there!"}]...}}Failed OpenClaw Request Pattern
[gateway] agent model: google/gemini-2.5-flash
[gateway] ready
[google] Google Generative AI API error (400)
[google] rawErrorPreview: Google Generative AI API error (400)Environment Details
- OpenClaw version: 2026.5.3-1
- OS: Ubuntu 24
- Install method: VPS with TailScale tunnel
- Tested models:
google/gemini-2.5-flash,google/gemma-4-31b-it
π§ Root Cause
Primary Suspect: Request Header Malformation
The critical diagnostic indicator is that the same API key succeeds via curl but fails in OpenClaw. This eliminates API key validity, network routing, and model availability as root causes, pointing definitively to request construction issues.
Potential Failure Vectors
- Authorization Header Collision
OpenClaw may be injecting an
Authorization: Bearerheader while Google API requires the proprietaryX-goog-api-keyheader. Some HTTP clients concatenate headers incorrectly:# Incorrect - OpenClaw may be sending both: Authorization: Bearer [API_KEY] X-goog-api-key: [API_KEY]Google API rejects this with 400
- Request Body Serialization Mismatch
Google's
generateContentendpoint has strict JSON schema requirements. OpenClaw may be:- Wrapping the request in an extra object layer
- Using incorrect field names (e.g.,
promptvscontents) - Serializing arrays incorrectly for the
partsstructure
- API Endpoint Version Drift
The working curl uses
v1betaendpoint. OpenClaw may be callingv1or an incorrect endpoint path:# Correct endpoint format: /v1beta/models/[MODEL_NAME]:generateContentPotential OpenClaw misconstruction:
/v1/models/[MODEL_NAME]:generateContent /v1beta/generateContent # Missing model name /v1/models/generateContent # Wrong path structure
- Content-Type or Accept Header Issues
Missing
Content-Type: application/jsonor incorrectAcceptheader can cause 400 errors. - TailScale Tunnel Interference
Network-level interference could modify headers in transit, though this is unlikely given curl succeeds through the same path.
Architectural Context
Given the regression nature (worked before), this suggests a recent update to the Google provider's request construction logic introduced a breaking change in header injection, body serialization, or endpoint construction.
π οΈ Step-by-Step Fix
Immediate Diagnostic Steps
- Enable debug logging to capture raw request:
OPENCLAW_LOG_LEVEL=debug openclaw [command] - Compare request traces - Look for header differences between successful curl and OpenClaw request
Workaround: Use OpenRouter as Intermediary
If the Google provider cannot be fixed immediately, route through OpenRouter which handles API compatibility:
# Update openclaw configuration
openclaw config set agent.model "openrouter/google/gemini-2.5-flash"
# Or via environment variable
export OPENCLAW_MODEL="openrouter/google/gemini-2.5-flash"Configuration Adjustment: Verify Auth Profile Structure
# Current (verify this matches):
openclaw config get auth.profiles
{
"google:default": {
"provider": "gemini",
"mode": "api_key"
}
}
# Alternative explicit configuration:
openclaw config set auth.profiles.google:default.provider "gemini"
openclaw config set auth.profiles.google:default.mode "api_key"
openclaw config set auth.profiles.google:default.api_key_env "GEMINI_API_KEY"Environment File Verification
# Ensure ~/.openclaw/.env contains:
GEMINI_API_KEY=AIzaSy...
# Verify no conflicting variables:
grep -E "(GOOGLE_API_KEY|AIza)" ~/.openclaw/.envRequest Provider Override (if available)
# Try explicit provider specification:
openclaw config set agent.provider "google"
openclaw config set agent.model "gemini-2.5-flash" # Without google/ prefixπ§ͺ Verification
Test 1: Direct Curl Verification (Baseline)
# Execute this exact request to establish baseline:
curl -s -w "\nHTTP_CODE:%{http_code}" \
"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent" \
-H 'Content-Type: application/json' \
-H 'X-goog-api-key: YOUR_ACTUAL_KEY' \
-X POST \
-d '{"contents":[{"parts":[{"text":"test"}]}]}'
# Expected: HTTP_CODE:200 with JSON responseTest 2: OpenClaw Configuration Validation
# Verify auth profile exists and is correct:
openclaw config get auth.profiles.google:default
# Expected: {"provider": "gemini", "mode": "api_key"}
# Verify model mapping:
openclaw models list | grep -i google
# Expected: List of available google/* modelsTest 3: Simple Completion Test
# Minimal test with debug output:
OPENCLAW_LOG_LEVEL=debug openclaw chat "Hi" --model google/gemini-2.5-flash 2>&1 | head -50
# Success indicators:
# - No "400" error in output
# - Contains "Hi" or response text
# - Exit code 0Test 4: Alternative Model Verification
# Test with different model to isolate model-specific issues:
openclaw chat "test" --model google/gemini-1.5-flash
# Test Gemma specifically:
openclaw chat "test" --model google/gemma-4-31b-itTest 5: OpenRouter Fallback Verification
# If using OpenRouter workaround:
openclaw chat "test" --model openrouter/google/gemini-2.5-flash
# Expected: Success with response from Gemini modelExpected Success Output
{
"message": "Hi there! I'm doing well, thank you for asking...",
"model": "gemini-2.5-flash",
"provider": "google",
"usage": {...}
}β οΈ Common Pitfalls
Environment Variable Collision
- Multiple API key environment variables can cause provider confusion
- Check for conflicts:
GOOGLE_API_KEY,GEMINI_API_KEY,OPENAI_API_KEY - Ensure only the correct variable is set in
~/.openclaw/.env
# Wrong - multiple keys:
GEMINI_API_KEY=xxx
GOOGLE_API_KEY=yyy # May override or conflict
# Correct - single key:
GEMINI_API_KEY=xxxModel Name Format Inconsistencies
- Some versions require
google/gemini-2.5-flashprefix - Others require bare
gemini-2.5-flash - API endpoint differences:
v1betavsv1
TailScale/Network-Specific Issues
- DNS resolution may differ between local and VPS environments
- MTU/fragmentation issues with large requests
- Proxy headers may be added unintentionally
Version-Specific Provider Bugs
- Version 2026.5.3-1 exhibits this regression
- Check if downgrading resolves issues:
# Check current version:
openclaw --version
# If downgrade needed (caution - may affect other functionality):
# Consult documentation for version installation proceduresAuth Profile Priority
- Multiple overlapping auth profiles can cause unexpected behavior
- Explicitly specify profile:
auth.profiles.google:default - Clear orphaned profiles:
openclaw config unset auth.profiles.google:alternate 2>/dev/null
openclaw config get auth.profilesAPI Quota and Regional Restrictions
- Google API keys can be restricted to specific domains/IPs
- VPS IP may not be whitelisted in Google Cloud Console
- Check Google Cloud Console β APIs & Services β Credentials
π Related Errors
Authentication and Header Errors
401 Unauthorized- Invalid or missing API key, typically indicates key not being passed correctly403 Forbidden- API key lacks permissions or is restricted to specific APIs429 Too Many Requests- Rate limiting; different from 400 but may appear in logs
Request Format Errors
400: Invalid JSON- Request body serialization failure400: Required field 'contents' not present- Incorrect request schema400: Invalid model name- Model not found or not available for API key
Network and Connectivity Errors
Connection timeout- Network routing issue, particularly relevant with TailScaleSSL certificate verification failed- TLS/intermediate certificate issueDNS resolution failure- Cannot reachgenerativelanguage.googleapis.com
OpenClaw Internal Errors
Provider not configured- Auth profile missing or misconfiguredModel not found- Model name not in provider's supported listNo valid auth credentials- API key not found in environment
Historical Related Issues
- OpenRouter provider works - Indicates issue is specifically with OpenClaw's Google provider implementation
- Curl succeeds - Confirms API endpoint, authentication, and network path are valid
- Regression pattern - Previously working Google integration now fails, pointing to recent code changes