[Error 429 de límite de tasa afecta todo el proveedor en lugar de un modelo específico] - Google Gemini Provider: 429 Rate Limit Scopes to Entire Provider Instead of Specific Model
Cuando un único modelo de Google Gemini alcanza el límite de tasa (429), la puerta de enlace OpenClaw aplica backoff a todo el proveedor 'google', bloqueando el acceso a otros modelos no relacionados con cuotas independientes.
🔍 Síntomas
Manifestación Principal
Cuando un modelo específico de Google Gemini agota su cuota, todas las solicitudes posteriores a cualquier modelo bajo el proveedor google fallan con errores de límite de tasa, incluso cuando esos modelos tienen asignaciones de cuota independientes.
Ejemplos de Salida de Error
Respuesta directa de API (429 de Google):
HTTP/1.1 429 Too Many Requests
Content-Type: application/json
{
"error": {
"code": 429,
"message": "Resource has been exhausted (e.g. check quota).",
"status": "RESOURCE_EXHAUSTED"
}
}
Respuesta del gateway OpenClaw después de que se active el retroalimentación:
{
"error": {
"type": "rate_limit_exceeded",
"provider": "google",
"message": "Provider 'google' is currently in cooldown due to rate limiting. Retry-After: 120s",
"retry_after": 120
}
}
Síntomas de Comportamiento
- Sin Aislamiento de Modelo: Cambiar de
gemini-3.1-pro-preview-customtoolsagemini-3.0-pro-previewno restaura la funcionalidad. - Indisponibilidad Extendida: Todas las solicitudes del proveedor
googlefallan hasta que expire el enfriamiento a nivel de proveedor. - Sin Ruta de Respaldo: Los modelos alternativos bajo el mismo proveedor no pueden servir como respaldo durante eventos de límite de tasa.
- Rechazo a Nivel de Gateway: Las solicitudes pueden ser rechazadas en la capa del gateway OpenClaw antes de llegar a la API de Google.
Escenario de Reproducción
# Paso 1: Solicitud al modelo con límite de tasa
curl -X POST https://api.openclaw.io/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model": "gemini-3.1-pro-preview-customtools", "messages": [{"role": "user", "content": "test"}]}'
# Respuesta: 429 de Google API
# Paso 2: Respaldo inmediato a otro modelo
curl -X POST https://api.openclaw.io/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model": "gemini-3.0-pro-preview", "messages": [{"role": "user", "content": "test"}]}'
# Esperado: La solicitud procede a Google API
# Actual: 429 o error de retroalimentación del gateway OpenClaw
🧠 Causa Raíz
Análisis de Arquitectura
La causa raíz reside en la implementación del seguimiento de límite de tasa a nivel de proveedor dentro del mecanismo de reintento/retroalimentación del gateway OpenClaw.
Secuencia de Falla
- Solicitud a
gemini-3.1-pro-preview-customtools: El despliegue específico del modelo recibe un429 RESOURCE_EXHAUSTEDde la API de Google. - Gateway Intercepta 429: El middleware de manejo de errores de OpenClaw captura la respuesta 429.
- Activación de Retroalimentación a Nivel de Proveedor: En lugar de registrar el límite de tasa contra el modelo/despliegue específico, el gateway establece un temporizador de enfriamiento en el identificador del proveedor
google. - Solicitud Subsecuente a
gemini-3.0-pro-preview: El gateway verifica si el proveedorgoogleestá en enfriamiento. Al encontrar que lo está, rechaza la solicitud preventivamente con un error de retroalimentación. - Modelo con Cuota Independiente es Bloqueado:
gemini-3.0-pro-previewpuede tener una asignación de cuota completamente separada, pero no puede ser accedido.
Causa Raíz a Nivel de Código
El seguimiento de límite de tasa probablemente usa una estructura de datos similar a:
// Representación simplificada del comportamiento actual
const providerBackoff = {
"google": {
cooldownUntil: 1699999999999, // Unix timestamp
reason: "rate_limit",
retryAfter: 120
}
};
// Verificación de retroalimentación
function shouldReject(provider) {
return providerBackoff[provider]?.cooldownUntil > Date.now();
}
El problema: El retroalimentación está identificado por el nombre del proveedor (“google”) en lugar del identificador del modelo o despliegue.
Arquitectura de Cuota de Google Gemini API
Google Gemini API opera con:
- Cuotas específicas por modelo: Cada modelo (ej.
gemini-3.1-pro-preview-customtools) tiene límites de tasa independientes. - Cuotas a nivel de proyecto: Límites más amplios que afectan a todos los modelos, pero típicamente son mucho más altos.
- Endpoints regionales: Pueden tener límites independientes.
Rutas de Código Divergentes
| Escenario | Comportamiento Actual | Comportamiento Esperado |
|---|---|---|
| Modelo A recibe 429 | Todo el proveedor google bloqueado | Solo Modelo A bloqueado |
| Cuota de Modelo A agotada | Modelo B inutilizable | Modelo B continúa si hay cuota disponible |
| Retroalimentación de proveedor activo | Gateway rechaza en capa 7 | Solicitud procede a API |
🛠️ Solución Paso a Paso
Opción 1: Habilitar Limitación de Tasa por Modelo (Recomendado)
Si OpenClaw soporta seguimiento de límite de tasa por modelo, configura el gateway para usar retroalimentación a nivel de modelo:
Antes (openclaw.yaml):
providers:
google:
api_key: "${GOOGLE_API_KEY}"
rate_limit:
strategy: "provider" # Actual: bloquea todo el proveedor
retry_after: 120
Después:
providers:
google:
api_key: "${GOOGLE_API_KEY}"
rate_limit:
strategy: "model" # Cambiado: seguimiento por modelo
retry_after: 120
scope: "deployment" # Granularidad: nivel de modelo/despliegue
Opción 2: Configurar Respaldos Específicos por Modelo
Define cadenas de respaldo explícitas para evitar modelos con límite de tasa:
Antes:
models:
- name: "gemini-3.1-pro-preview-customtools"
provider: "google"
Después:
models:
- name: "gemini-3.1-pro-preview-customtools"
provider: "google"
fallback_models:
- "gemini-3.0-pro-preview"
- "gemini-pro"
- name: "gemini-3.0-pro-preview"
provider: "google"
fallback_models:
- "gemini-pro"
Opción 3: Aumentar Granularidad del Enfriamiento del Proveedor (Corrección de Código)
Si tienes acceso al código fuente de OpenClaw, modifica el seguimiento de límite de tasa:
Paso 1: Identificar el manejador de límite de tasa
Localiza el archivo que maneja respuestas 429. Típicamente encontrado en:
src/gateway/middleware/rate-limit-handler.ts
src/providers/google/error-handler.ts
Paso 2: Modificar la clave de retroalimentación de proveedor a modelo
// ANTES (a nivel de proveedor)
providerBackoff[provider] = {
cooldownUntil: Date.now() + retryAfter * 1000,
reason: "rate_limit"
};
// DESPUÉS (a nivel de modelo)
const modelKey = `${provider}:${model}`;
modelBackoff[modelKey] = {
cooldownUntil: Date.now() + retryAfter * 1000,
reason: "rate_limit",
model: model,
provider: provider
};
Paso 3: Actualizar la verificación de rechazo
// ANTES
function shouldReject(request) {
const provider = request.provider;
return providerBackoff[provider]?.cooldownUntil > Date.now();
}
// DESPUÉS
function shouldReject(request) {
const modelKey = `${request.provider}:${request.model}`;
const providerKey = request.provider;
// Verificar retroalimentación específica del modelo primero
if (modelBackoff[modelKey]?.cooldownUntil > Date.now()) {
return { rejected: true, reason: "model_rate_limited" };
}
// Respaldo a nivel de proveedor solo para límites compartidos
if (providerBackoff[providerKey]?.cooldownUntil > Date.now()) {
return { rejected: true, reason: "provider_rate_limited" };
}
return { rejected: false };
}
Opción 4: Solución Alternativa via Múltiples Instancias de Proveedor
Crea configuraciones de proveedor separadas para modelos con cuotas independientes:
providers:
google-gemini-31:
api_key: "${GOOGLE_API_KEY}"
models:
- "gemini-3.1-pro-preview-customtools"
rate_limit:
retry_after: 60
google-gemini-30:
api_key: "${GOOGLE_API_KEY}"
models:
- "gemini-3.0-pro-preview"
rate_limit:
retry_after: 60
google-gemini-pro:
api_key: "${GOOGLE_API_KEY}"
models:
- "gemini-pro"
rate_limit:
retry_after: 60
🧪 Verificación
Prueba 1: Confirmar Aislamiento a Nivel de Modelo Después de la Corrección
# Paso 1: Activar límite de tasa en modelo A
curl -X POST https://api.openclaw.io/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model": "gemini-3.1-pro-preview-customtools", "messages": [{"role": "user", "content": "test"}]}'
# Esperado: 429 de Google API
# Verificar con: echo $? (debe ser distinto de cero)
# Paso 2: Probar inmediatamente acceso al modelo B
curl -X POST https://api.openclaw.io/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model": "gemini-3.0-pro-preview", "messages": [{"role": "user", "content": "test"}]}'
# Esperado: 200 OK o respuesta válida de API (no error de retroalimentación del gateway)
Prueba 2: Verificar Estado de Retroalimentación Específico del Modelo
Verifica el estado interno del gateway (si se expone via endpoint de administración):
GET /admin/rate-limit-status
# Estructura de respuesta esperada:
{
"providers": {
"google": {
"cooldown": false,
"models": {
"gemini-3.1-pro-preview-customtools": {
"cooldown": true,
"retry_after": 120,
"expires_at": "2024-01-15T10:30:00Z"
},
"gemini-3.0-pro-preview": {
"cooldown": false
}
}
}
}
}
Prueba 3: Prueba de Disponibilidad de Modelos Concurrentes
# Ejecutar solicitudes concurrentes a diferentes modelos
for model in "gemini-3.1-pro-preview-customtools" "gemini-3.0-pro-preview" "gemini-pro"; do
echo "Probando: $model"
curl -s -o /dev/null -w "%{http_code}\n" \
-X POST https://api.openclaw.io/v1/chat/completions \
-H "Content-Type: application/json" \
-d "{\"model\": \"$model\", \"messages\": [{\"role\": \"user\", \"content\": \"test\"}]}"
done
# Esperado:
# gemini-3.1-pro-preview-customtools: 429 (límite de tasa)
# gemini-3.0-pro-preview: 200 (cuota independiente)
# gemini-pro: 200 (cuota independiente)
Prueba 4: Verificación de Expiración del Retroalimentación
# Esperar a que expire el enfriamiento
echo "Esperando expiración del enfriamiento del modelo..."
sleep 130 # retry_after + buffer
# Verificar que el modelo previamente limitado esté accesible
curl -X POST https://api.openclaw.io/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model": "gemini-3.1-pro-preview-customtools", "messages": [{"role": "user", "content": "test"}]}'
# Esperado: 200 OK
Criterios de Éxito
- ✅ Después del límite de tasa en
gemini-3.1-pro-preview-customtools, otros modelosgooglepermanecen accesibles. - ✅ El estado de retroalimentación específico del modelo se rastrea correctamente y expira independientemente.
- ✅ El gateway no rechaza preventivamente solicitudes a modelos sin límite de tasa.
- ✅ Las cadenas de respaldo funcionan correctamente cuando el modelo primario no está disponible.
⚠️ Errores Comunes
Trampas Específicas del Entorno
Caché de Contenedores Docker
# Trampa: El sistema de archivos del contenedor puede caché el estado de límite de tasa
# Reiniciar contenedores puede no restablecer el estado si la persistencia está habilitada
docker-compose down
docker volume prune openclaw-cache # Limpiar estado en caché
docker-compose up -d
Montajes de Volumen en Kubernetes
Si usas volúmenes persistentes para el seguimiento de límite de tasa:
# Verificar que el PVC no esté desactualizado después de cambios de configuración
kubectl get pvc | grep openclaw
kubectl describe pvc openclaw-cache
# Puede ser necesario eliminar y recrear si el esquema cambió
kubectl delete pvc openclaw-cache
# Luego reiniciar los despliegues
Entorno de Desarrollo macOS
# Trampa: El estado local de límite de tasa puede persistir entre sesiones de terminal
# Limpiar cualquier archivo de estado local
rm -rf ~/.openclaw/cache/*
rm -rf .openclaw/state.json
Errores de Configuración
Nombre Incorrecto de Proveedor en Cadena de Respaldo
# INCORRECTO: Errores tipográficos en el nombre del proveedor causan fallas silenciosas
models:
- name: "gemini-3.0-pro-preview"
provider: "googel" # Error tipográfico - no coincidirá con el proveedor real
# CORRECTO:
models:
- name: "gemini-3.0-pro-preview"
provider: "google"
Declaraciones de Modelo Superpuestas
# INCORRECTO: Mismo modelo declarado múltiples veces
models:
- name: "gemini-3.0-pro-preview"
provider: "google"
- name: "gemini-3.0-pro-preview" # Duplicado
provider: "google"
fallback_models: [...]
Desajuste de Alcance de Clave API
# Trampa: Las claves API de Google pueden tener diferentes cuotas por proyecto
# Si usas instancias de proveedor separadas, asegúrate de que usen claves con cuotas adecuadas
# Verificar en Google Cloud Console:
# APIs & Services > Enabled APIs > Vertex AI API > Quotas
Casos de Prueba Extremos
Límite de Tasa en Último Modelo Disponible
# Escenario: Todos los modelos bajo un proveedor tienen límite de tasa
# Esperado: Debe devolver un error claro, no un éxito silencioso
# Verificar que la respuesta de error incluya todos los modelos afectados
curl -X POST https://api.openclaw.io/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model": "gemini-3.0-pro-preview", "messages": [{"role": "user", "content": "test"}]}'
# Verificar que la respuesta contenga información accionable
# NO debe ser un 200 OK vacío
Cambio Rápido de Modelo
# Trampa: Condición de carrera durante cambio rápido puede evadir el retroalimentación
# Probar con solicitudes concurrentes
ab -n 100 -c 10 -T 'application/json' \
-p request.json \
https://api.openclaw.io/v1/chat/completions
# Verificar que todas las solicitudes estén correctamente limitadas o procesadas
🔗 Errores Relacionados
| Código de Error | Descripción | Conexión |
|---|---|---|
429 RESOURCE_EXHAUSTED | La API de Google devolvió error de límite de tasa | Error fuente que activa el retroalimentación del proveedor |
503 Service Unavailable | Proveedor temporalmente no disponible | Derivado de retroalimentación de proveedor prolongado |
500 Internal Server Error | Error del gateway durante manejo de retroalimentación | Excepción no manejada en middleware de límite de tasa |
ENOTFOUND | Fallo de resolución DNS para API de Google | Sin relación pero puede ser mal diagnosticado como límite de tasa |
ETIMEDOUT | Tiempo de conexión agotado a API de Google | Sin relación pero puede activar lógica de retroalimentación incorrecta |
INVALID_ARGUMENT | Solicitud mal formada a API de Gemini | Puede ser mal enrutado como límite de tasa en manejo de errores |
Contexto Histórico
Este problema se relaciona con patrones más amplios en el diseño de gateways de API multi-tenant:
- Cortacircuitos Demasiado Amplios: Aplicar patrones de cortacircuitos a nivel de proveedor cuando deberían operar a nivel de modelo/despliegue.
- Colisión de Estado Compartido: Múltiples recursos independientes compartiendo un único contador de límite de tasa.
- Contexto de Error Insuficiente: Las respuestas 429 de Google incluyen
retryInfoque especifica qué cuota fue agotada, pero esto puede no ser analizado.
Issues de GitHub Relacionados
- El límite de tasa debe ser alcance por modelo, no por proveedor - Solicitud de característica para aislamiento a nivel de modelo
- El retroalimentación del proveedor Google Gemini bloquea todos los modelos - Issue de seguimiento duplicado
- Agregar análisis de retry-after desde respuestas 429 de Google - Mejora para cálculo preciso de enfriamiento