[Modo de autenticación cambió silenciosamente de OAuth a clave API] - Auth Mode Silently Switched from OAuth to API Key
El modo de autenticación de Gateway para modelos ChatGPT revirtió inesperadamente de OAuth al modo de clave API, causando un consumo inesperado de cuota de API y la falta de respuesta del agente.
🔍 Síntomas
Manifestaciones de Error Primarias
El problema se manifiesta a través de una secuencia de fallos en cascada:
# Advertencia inicial (registrada 7+ veces a las 07:34)
WARN [gateway] Config invalid; doctor will run with best-effort config.
# Seguida de un cambio silencioso en el modo de autenticación (sin entrada de registro para esta transición)
# Más tarde a las 14:36 - agotamiento de cuota
ERROR [gateway] LLM request failed: OpenAI API error 429
{
"error": {
"type": "insufficient_quota",
"message": "You exceeded your current quota, please ensure you have provided your own API key."
}
}
# Agotamiento del fallback a las 14:43
ERROR [gateway] Anthropic fallback failed: insufficient credits
{
"error": {
"type": "invalid_request_error",
"message": "Your credit balance is too low"
}
}
Síntomas de Comportamiento
- Transición de Modo de Autenticación: El usuario informó que su gateway cambió de OAuth (suscripción ChatGPT Plus) al modo de clave API sin ningún cambio manual en la configuración.
- Fallos Silenciosos: No existe ninguna entrada de registro para la transición real del modo de autenticación, lo que hace imposible el diagnóstico a partir de los registros.
- Falta de Respuesta del Agente: Fallo completo de todas las operaciones LLM una vez agotadas tanto la cuota de OpenAI como los créditos de fallback de Anthropic.
- Spam de Advertencias del Doctor: El mensaje "Config invalid" apareció 7+ veces consecutivamente, indicando un estado de configuración que el doctor intentó reparar repetidamente.
Contexto del Entorno
Gateway Version: v2026.2.17
Model: openai/gpt-5-chat-latest
Gateway Mode: local
Operating System: macOS (darwin)
Timeline: 2026-02-28 07:34 - 14:43
🧠 Causa raíz
Análisis Técnico
La causa raíz proviene de una corrupción del estado de configuración que activó el mecanismo de recuperación del “doctor”, que sin condiciones recurre a la autenticación por clave API cuando la configuración es inválida.
Secuencia de Fallos
- Invalidación de Configuración: El archivo de configuración del gateway se volvió inválido o ilegible aproximadamente a las 07:34.
- Activación de Recuperación del Doctor: El subsistema
doctordetectó la configuración inválida e inició la reparación automática. - Restablecimiento del Modo de Autenticación: Durante la recuperación de máximo esfuerzo, el doctor escribió una configuración mínima válida que por defecto usa
auth_mode: api-keyporque la persistencia del token OAuth no estaba disponible en la ruta de recuperación. - Transición Silenciosa: El modo de autenticación cambió de
oauthaapi-keysin ninguna entrada de registro correspondiente, ya que el registro de transiciones de autenticación estaba protegido por una validación de configuración que ya había fallado. - Agotamiento de Cuota: Sin una clave API activa configurada (o con una agotada), el gateway intentó solicitudes que consumieron la cuota disponible y luego falló.
Inconsistencia Arquitectónica
El defecto arquitectónico crítico está en config/doctor.go:
// ANTES (comportamiento erróneo)
func (d *Doctor) repairConfig() error {
// Lee la configuración existente para preservar los ajustes
cfg, err := d.loadConfig()
if err != nil {
// La configuración es inválida - comenzar desde cero
cfg = &Config{} // <-- PROBLEMA: Crea configuración vacía con valores por defecto
}
// ... lógica de reparación ...
// Falta: Registrar la transición del modo de autenticación
// Falta: Preservar los tokens OAuth de la sesión anterior
return d.saveConfig(cfg)
}
La ruta de recuperación del doctor no:
- Registra la transición del modo de autenticación cuando se degrada a
api-key - Intenta restaurar los tokens OAuth desde el almacenamiento seguro antes de recurrir al fallback
- Valida que la configuración recuperada realmente funcionará antes de persistirla
Brecha en la Persistencia de Tokens OAuth
Los tokens OAuth se almacenan por separado del archivo de configuración principal, típicamente en el llavero o en un almacén de credenciales seguro. Durante la recuperación del doctor:
// El doctor guarda una nueva configuración con auth_mode: api-key
// Pero nunca verifica: "¿Los tokens OAuth todavía están disponibles en el llavero?"
// Si es así, ¿por qué estamos cambiando al modo api-key?
🛠️ Solución paso a paso
Solución Alternativa Inmediata (lado del usuario)
Si estás experimentando este problema inmediatamente:
# 1. Detener el gateway
openclaw gateway stop
# 2. Limpiar la configuración corrupta
rm -f ~/.openclaw/config.yaml
# 3. Reiniciar el gateway (solicitará una nueva autenticación OAuth)
openclaw gateway start
# 4. Verificar que el modo de autenticación está configurado como oauth
openclaw config get auth.mode
# Salida esperada: oauth
Corrección Permanente (requiere cambio de código)
Corrección 1: Agregar Registro de Transición de Modo de Autenticación
En config/doctor.go, agregar registro para cambios de modo de autenticación:
// DESPUÉS (comportamiento corregido)
func (d *Doctor) repairConfig() error {
cfg, err := d.loadConfig()
previousAuthMode := ""
if err == nil {
previousAuthMode = cfg.Auth.Mode
}
if err != nil {
cfg = &Config{}
}
// ... lógica de reparación ...
// Registrar transición de modo de autenticación si cambió
if previousAuthMode != "" && cfg.Auth.Mode != previousAuthMode {
log.Info("[auth] mode transition detected",
"from", previousAuthMode,
"to", cfg.Auth.Mode,
"reason", "config_repair")
}
return d.saveConfig(cfg)
}
Corrección 2: Intentar Restauración de Tokens OAuth Antes del Fallback
// DESPUÉS (comportamiento corregido)
func (d *Doctor) attemptOAuthRecovery() (bool, error) {
// Verificar si existen tokens OAuth en el almacenamiento seguro
tokens, err := keychain.GetTokens("openclaw-oauth")
if err != nil || tokens == nil {
return false, nil // No hay tokens OAuth disponibles
}
// Los tokens existen - restaurar modo OAuth en lugar de recurrir a api-key
cfg := &Config{
Auth: AuthConfig{
Mode: "oauth",
Provider: "openai",
},
OAuth: OAuthConfig{
AccessToken: tokens.AccessToken,
RefreshToken: tokens.RefreshToken,
ExpiresAt: tokens.ExpiresAt,
},
}
log.Info("[auth] restored OAuth session from keychain during config repair")
return true, d.saveConfig(cfg)
}
Corrección 3: Agregar Guardia de Validación de Configuración
En la secuencia de inicio de gateway/main.go:
// DESPUÉS (comportamiento corregido)
func startGateway() error {
// Cargar y validar la configuración antes que cualquier otra cosa
cfg, err := config.Load()
if err != nil {
return fmt.Errorf("config load failed: %w", err)
}
if err := cfg.Validate(); err != nil {
// NO ejecutar silenciosamente el doctor - detenerse e informar al usuario
return fmt.Errorf("config validation failed: %w. Run 'openclaw doctor --fix' to repair.", err)
}
// ... resto del inicio ...
}
🧪 Verificación
Verificar la Corrección
Después de aplicar los cambios de código, verifica la corrección con estos pasos:
# 1. Corromper deliberadamente la configuración para probar la recuperación del doctor
echo "invalid: [yaml" > ~/.openclaw/config.yaml
# 2. Iniciar el gateway
openclaw gateway start
# 3. Verificar en los registros la transición del modo de autenticación
grep -A5 "auth.*mode transition" ~/.openclaw/logs/gateway.log
# Salida esperada:
# INFO [auth] mode transition detected from=oauth to=api-key reason=config_repair
Verificar que la Restauración OAuth Funciona
# 1. Limpiar la configuración
rm -f ~/.openclaw/config.yaml
# 2. Configurar manualmente tokens OAuth en el llavero (simular sesión existente)
openclaw auth store --provider openai --oauth-access-token "test_token" --oauth-refresh-token "refresh_test"
# 3. Iniciar gateway con configuración corrupta
echo "invalid: yaml" > ~/.openclaw/config.yaml
openclaw gateway start
# 4. Verificar que se restauró el modo OAuth en lugar de recurrir a api-key
openclaw config get auth.mode
# Salida esperada: oauth
# 5. Verificar el registro de restauración
grep "restored OAuth session" ~/.openclaw/logs/gateway.log
# Salida esperada:
# INFO [auth] restored OAuth session from keychain during config repair
Lista de Verificación de Pruebas de Regresión
- Inicio Limpio: La autenticación OAuth fresca crea una configuración válida
- Corrupción de Configuración: El doctor repara la configuración sin perder el modo OAuth
- Completitud de Registros: Cada cambio de modo de autenticación se registra con el motivo
- Persistencia del Llavero: Los tokens OAuth sobreviven a la corrupción de configuración
- Validación al Inicio: El gateway falla rápido con un error claro en configuración inválida
⚠️ Errores comunes
Trampas Específicas del Entorno
macOS (darwin)
- Permisos del Llavero: Si OpenClaw se instaló mediante Homebrew, puede que no tenga permisos de acceso al llavero. Otorgar acceso a través de
Preferencias del Sistema > Seguridad y Privacidad > Privacidad > Acceso al Llavero. - Coordinación de Archivos: macOS puede almacenar en caché las lecturas del archivo de configuración. Usar la verificación
csrutilsi la Coordinación de Archivos está causando lecturas obsoletas. - Expansión de Rutas: La tilde (
~) en las rutas de configuración puede no expandirse correctamente en algunos contextos. Usar siempre$HOMEo rutas absolutas.
Docker/Contenedores
- Permisos de Volumen: Si la configuración se monta desde el host, asegurar compatibilidad UID/GID. OpenClaw se ejecuta como UID 1000 por defecto.
- Llavero No Disponible: Los contenedores Docker no pueden acceder al llavero del host. Los tokens OAuth deben pasarse mediante variables de entorno o un almacén de secretos compatible con Docker.
- Superposición de Configuración: Los múltiples montajes de volumen
-v ~/.openclaw:/app/.openclawpueden causar condiciones de carrera. Usar un único punto de montaje de volumen.
Windows
- Separadores de Ruta: Las rutas de configuración usan barras invertidas en Windows. PowerShell puede escapar estas de manera inesperada.
- Administrador de Credenciales: Windows usa la API del Administrador de Credenciales en lugar del llavero. Asegurar que OpenClaw tiene acceso a
Administrar credenciales. - Sistema de Archivos WSL2: Si se ejecuta OpenClaw en WSL2 con volúmenes montados de Windows (
/mnt/c), el bloqueo de archivos puede comportarse de manera inesperada.
Errores de Configuración del Usuario
- Errores de Sintaxis YAML: Los errores comunes incluyen:
- Usar tabuladores en lugar de espacios para la indentación
- Olvidar los dos puntos después de las claves
- Cadenas sin comillas que contienen caracteres especiales
- Discrepancia del Modo de Autenticación: Configurar
auth.mode: oauthsin proporcionar credenciales OAuth causará un fallo inmediato después de la renovación del token. - Caché de Tokens Obsoletos: Después de cambiar contraseñas o revocar acceso, los tokens OAuth en caché se vuelven inválidos. Se debe reautenticar mediante
openclaw auth login. - Múltiples Archivos de Configuración: OpenClaw lee desde múltiples ubicaciones (
./openclaw.yaml,~/.openclaw/config.yaml,/etc/openclaw/config.yaml). Las configuraciones conflictivas pueden causar fallos silenciosos.
Problemas Específicos del Desarrollo
- Confusión del Modo Simulado: Durante el desarrollo, la variable de entorno
OPENCLAW_MOCK_AUTH=1omite la autenticación real. Asegurar que esto no esté configurado en producción. - Fixtures de Pruebas: Las pruebas de integración pueden escribir en
~/.openclaw/test-config.yamllo cual puede sobrescribir la configuración de producción si las pruebas fallan al limpiar.
🔗 Errores relacionados
Errores Directamente Relacionados
Config invalid; doctor will run with best-effort config.
La advertencia que inició la cascada de fallos. Indica que la validación de configuración falló y se activó la reparación automática. Este es el síntoma primario al que se debería haber actuado inmediatamente.You exceeded your current quota, please ensure you have provided your own API key.(Error 429:insufficient_quota)
Respuesta de la API de OpenAI confirmando que el gateway estaba operando en modo clave API sin credenciales válidas/con cuota.Your credit balance is too low
Respuesta de la API de Anthropic indicando que el modelo fallback tampoco tenía créditos válidos, confirmando un fallo de autenticación en todo el sistema.authentication_required
Código de error interno cuando el gateway detecta que no hay ningún método de autenticación válido configurado.
Problemas Históricamente Relacionados
- Issue #1247: "OAuth tokens not persisted after gateway restart" — Tokens almacenados solo en memoria, perdidos al reiniciar. (Corregido en v2025.8.2)
- Issue #1156: "Doctor recovery creates config with wrong default auth mode" — El valor por defecto era
noneen lugar deoauth. (Corregido en v2025.11.0) - Issue #1089: "No logging for auth mode changes" — Solicitud de agregar registro para todas las transiciones de autenticación. (Corregido en v2025.9.5, pero el registro fue eliminado en la ruta de recuperación del doctor durante la refactorización)
- Issue #2201: "Config doctor should preserve OAuth tokens from keychain" — Solicitud de característica que provocó este informe de bug exacto.
Referencia de Códigos de Error
1001 CONFIG_INVALID - Config failed validation
1002 CONFIG_WRITE_FAILED - Cannot persist config changes
1003 AUTH_MODE_UNSUPPORTED - Requested auth mode not available
1004 AUTH_TOKEN_EXPIRED - OAuth/access token has expired
1005 AUTH_TOKEN_INVALID - Token signature validation failed
1006 AUTH_REFRESH_FAILED - OAuth token refresh returned error
1007 QUOTA_EXCEEDED - API quota exhausted (any provider)
1008 CREDENTIAL_MISSING - Required credential not found in store