April 15, 2026 • Versión: v2026.4.14-beta.1

El menú desplegable de modelos muestra modelos de proveedores no configurados - Dashboard Model Dropdown Displays Models from Unconfigured Providers

El menú desplegable de selección de modelo del Agente en el Dashboard de OpenClaw muestra todos los modelos compatibles independientemente del estado de configuración del proveedor, lo que causa confusión al usuario al seleccionar modelos no disponibles.

🔍 Síntomas

Comportamiento reportado por el usuario

Al acceder al Dashboard en http://localhost:8080 y navegar a Configuración del Agente, el menú desplegable de Modelo Principal muestra una lista extensa de modelos:

┌─────────────────────────────────────────────────────────┐
│  Primary Model                                    ▼     │
├─────────────────────────────────────────────────────────┤
│  🔍 Search models...                                     │
├─────────────────────────────────────────────────────────┤
│  ▼ Alibaba Cloud (bailian)                              │
│      bailian/kimi-k2.5                                  │
│      bailian/qwen-plus                                  │
│  ▼ Anthropic                                            │
│      anthropic/claude-opus-4-5                         │
│      anthropic/claude-sonnet-4                          │
│  ▼ Amazon Bedrock                                       │
│      bedrock/anthropic.claude-3-5-sonnet               │
│      bedrock/anthropic.claude-3-opus                    │
│  ▼ OpenAI                                               │
│      openai/gpt-4o                                       │
│      openai/gpt-4-turbo                                  │
└─────────────────────────────────────────────────────────┘

Escenario de fallo

Cuando un usuario selecciona un modelo de un proveedor no configurado (por ejemplo, anthropic/claude-opus-4-5) e intenta guardar o usar el agente:

$ openclaw agent update --model anthropic/claude-opus-4-5
[ERROR] Provider 'anthropic' is not configured. 
        Please configure credentials in config.yaml or set environment variables.
        Run 'openclaw config list' to see current provider status.

Manifestación técnica

En la consola del navegador, el componente del menú desplegable renderiza los modelos desde src/models/supported-models.json sin verificar la disponibilidad del proveedor:

[OpenClaw] Model list loaded: 127 models
[OpenClaw] Provider check skipped for dropdown population

🧠 Causa raíz

Problema arquitectónico

El componente selector de modelos del Dashboard (src/components/ModelSelector.tsx) carga la lista completa de modelos soportados desde el registro estático de modelos durante la inicialización del componente:

// src/components/ModelSelector.tsx - Line 23-45
function ModelSelector() {
  const [models, setModels] = useState<Model[]>([]);
  
  useEffect(() => {
    // Current implementation - loads ALL models
    const allModels = getSupportedModels();
    setModels(allModels);
  }, []);
  
  // ... rest of component
}

Verificación de disponibilidad del proveedor faltante

El componente no llama a getConfiguredProviders() o equivalente para filtrar modelos por disponibilidad del proveedor. El registro de modelos y la configuración del proveedor existen en dominios de datos separados sin integración:

┌─────────────────────────────────┐
│  Models Registry                │
│  (src/models/supported-models.ts)│
│                                 │
│  • 127 models defined           │
│  • Grouped by provider          │
│  • No runtime validation        │
└───────────────┬─────────────────┘
                │
                ▼ NO INTEGRATION
┌─────────────────────────────────┐
│  Provider Configuration         │
│  (config.yaml / env vars)       │
│                                 │
│  • User-configured credentials  │
│  • Provider availability state  │
│  • NOT consulted by UI          │
└─────────────────────────────────┘

Brecha en el flujo de datos

  1. El usuario abre el Dashboard → El componente ModelSelector se monta
  2. El componente obtiene todos los modelosgetSupportedModels() devuelve la lista estática completa
  3. Sin llamada API al backend → El componente no consulta /api/providers/status
  4. El menú desplegable renderiza todos los modelos → Incluyendo los de proveedores no configurados
  5. El usuario selecciona un modelo inválido → El error de tiempo de ejecución ocurre solo en la ejecución

Ruta del código afectada

src/
├── components/
│   └── ModelSelector.tsx        ← Does not filter by provider config
├── services/
│   └── providerService.ts       ← Contains getConfiguredProviders() but unused
└── models/
    └── supported-models.ts      ← Returns unfiltered model list

🛠️ Solución paso a paso

Opción A: Filtrar modelos por proveedores configurados (Recomendado)

Modificar src/components/ModelSelector.tsx para filtrar modelos según la disponibilidad del proveedor:

// src/components/ModelSelector.tsx - FIXED IMPLEMENTATION
import { useState, useEffect } from 'react';
import { getSupportedModels, Model } from '../models/supported-models';
import { getConfiguredProviders } from '../services/providerService';

function ModelSelector({ onModelSelect }: Props) {
  const [models, setModels] = useState<Model[]>([]);
  const [configuredProviders, setConfiguredProviders] = useState<Set<string>>(new Set());
  const [showOnlyConfigured, setShowOnlyConfigured] = useState(true);
  
  useEffect(() => {
    async function loadData() {
      // Step 1: Get list of configured providers
      const providers = await getConfiguredProviders();
      const configuredSet = new Set(providers.map(p => p.id));
      setConfiguredProviders(configuredSet);
      
      // Step 2: Load all models
      const allModels = getSupportedModels();
      
      // Step 3: Filter to only configured providers
      const filteredModels = showOnlyConfigured
        ? allModels.filter(model => configuredSet.has(model.provider))
        : allModels;
      
      setModels(filteredModels);
    }
    
    loadData();
  }, [showOnlyConfigured]);
  
  // ... rest of component
}

Opción B: Agregar indicador visual para modelos no configurados

Si se mantiene la visibilidad de todos los modelos con distinción visual:

// src/components/ModelSelector.tsx - ALTERNATIVE FIX
function ModelSelector({ onModelSelect }: Props) {
  const [models, setModels] = useState<Model[]>([]);
  const [configuredProviders, setConfiguredProviders] = useState<Set<string>>(new Set());
  
  useEffect(() => {
    async function loadData() {
      const providers = await getConfiguredProviders();
      setConfiguredProviders(new Set(providers.map(p => p.id)));
      setModels(getSupportedModels());
    }
    loadData();
  }, []);
  
  const isProviderConfigured = (providerId: string) => {
    return configuredProviders.has(providerId);
  };
  
  return (
    <select onChange={(e) => onModelSelect(e.target.value)}>
      {models.map(model => (
        <option 
          key={model.id}
          value={model.id}
          disabled={!isProviderConfigured(model.provider)}
          style={{
            color: isProviderConfigured(model.provider) ? 'inherit' : '#999',
            backgroundColor: isProviderConfigured(model.provider) ? 'white' : '#f5f5f5'
          }}
        >
          {model.displayName}
          {!isProviderConfigured(model.provider) && ' ⚠️ (provider not configured)'}
        </option>
      ))}
    </select>
  );
}

Opción C: Filtrado controlado por el backend

Agregar un nuevo endpoint de API que devuelva solo los modelos disponibles:

// src/routes/api/models/available.ts
import { Router } from 'express';
import { getSupportedModels } from '../../models/supported-models';
import { getConfiguredProviders } from '../../services/providerService';

const router = Router();

router.get('/available', async (req, res) => {
  const configuredProviders = await getConfiguredProviders();
  const providerIds = new Set(configuredProviders.map(p => p.id));
  
  const availableModels = getSupportedModels()
    .filter(model => providerIds.has(model.provider));
  
  res.json({
    models: availableModels,
    configuredProviders: configuredProviders.map(p => p.id)
  });
});

export default router;

🧪 Verificación

Pasos de verificación

Después de aplicar la corrección, verificar el comportamiento a través de estos métodos:

1. Verificación de la interfaz de usuario del Dashboard

# Start the Dashboard
$ openclaw dashboard start

# Open browser to http://localhost:8080
# Navigate to Agent Settings → Primary Model dropdown
# 
# Expected: Only models from configured providers appear
# Example: If only bailian is configured, only bailian/* models show

2. Verificación del endpoint de API

# If using Option C (backend filtering)
$ curl http://localhost:8080/api/models/available | jq

# Expected output:
{
  "models": [
    {"id": "bailian/kimi-k2.5", "provider": "bailian", ...},
    {"id": "bailian/qwen-plus", "provider": "bailian", ...}
  ],
  "configuredProviders": ["bailian"]
}

# Should NOT contain anthropic, bedrock, openai models

3. Prueba unitaria del componente

# Run the ModelSelector component tests
$ npm test -- --grep "ModelSelector"

# Expected: Test passes verifying filtering logic
✓ filters models by configured provider
✓ shows visual indicator for unconfigured models
✓ updates when provider configuration changes

4. Prueba de integración

# Configure a new provider and verify dropdown updates
$ openclaw config add-provider anthropic --api-key sk-ant-...

# Refresh Dashboard
# Verify anthropic models now appear in dropdown

Verificación del código de salida

# Verify no console errors in Dashboard
$ openclaw dashboard start --debug 2>&1 | grep -i "model\|provider"

[DEBUG] Loading configured providers: ["bailian"]
[DEBUG] Filtering 127 models to 2 available (bailian)
[DEBUG] ModelSelector rendered with 2 options

⚠️ Errores comunes

Casos extremos a manejar

  • Sin proveedores configurados: El menú desplegable debe mostrar un estado vacío con el mensaje "Configure un proveedor para ver los modelos disponibles"
  • Proveedor configurado durante la sesión: ModelSelector debe volver a obtener la lista de proveedores al recibir el foco o en el evento de foco de la ventana
  • La clave API del proveedor se vuelve inválida: Los modelos permanecen visibles (la validación del lado del servidor maneja los errores de tiempo de ejecución)
  • Condición de carrera en la carga inicial: Mostrar esqueleto de carga mientras se obtiene la configuración del proveedor

Consideraciones específicas del entorno

Despliegue en Docker

# When running in Docker, provider config is read from:
# 1. Environment variables (PRIORITY)
# 2. Mounted config.yaml at /app/config.yaml

# Verify config is mounted correctly:
$ docker exec <container-id> cat /app/config.yaml | grep -A5 providers

# Expected: Shows configured providers

Instalación en macOS

# Config location: ~/.openclaw/config.yaml
# Verify file permissions:
$ ls -la ~/.openclaw/config.yaml
-rw-r--r--  openclaw ~/.openclaw/config.yaml

# If permission denied, fix with:
$ chmod 644 ~/.openclaw/config.yaml

Windows (WSL2)

# Config location: ~/.openclaw/config.yaml (WSL2 path)
# Or: C:\Users\<username>\.openclaw\config.yaml

# Ensure line endings are LF, not CRLF:
$ dos2unix ~/.openclaw/config.yaml 2>/dev/null || sed -i 's/\r$//' ~/.openclaw/config.yaml

Errores de configuración

ID de proveedor incorrecto en la configuración:
# WRONG - provider ID mismatch
providers:
  anthropic_api:
    type: anthropic    # Should match model provider name

CORRECT

providers: anthropic: type: anthropic

Campos requeridos faltantes:
# WRONG - missing api_key
providers:
  anthropic:
    type: anthropic
    # api_key is required

CORRECT

providers: anthropic: type: anthropic api_key: sk-ant-…

🔗 Errores relacionados

Problemas conectados

  • ERR_PROVIDER_NOT_CONFIGURED: Ocurre al intentar usar un modelo de un proveedor no configurado. Actualmente sucede en tiempo de ejecución en lugar de a nivel de interfaz de usuario.
  • ERR_API_KEY_INVALID: El proveedor está configurado pero las credenciales son inválidas. Relacionado con el menú desplegable que muestra modelos que pasan la verificación de configuración pero fallan en autenticación.
  • ERR_MODEL_NOT_FOUND: El formato del ID del modelo cambió pero la lista de modelos del Dashboard está desactualizada. Puede ocurrir después de una actualización de versión de OpenClaw.

Contexto histórico

VersiónProblemaResolución
v2026.3.xEl menú desplegable de proveedores muestra todos los proveedores independientemente de la configuraciónCorrección parcial - la lista de proveedores se filtra, la lista de modelos no
v2026.2.xLas credenciales API se almacenaban en texto plano en config.yamlSe agregó soporte de cifrado
v2026.1.xEl selector de modelos no respondía en listas de modelos grandesSe agregó desplazamiento virtual

Documentación relacionada

Comandos de depuración

# List configured providers
$ openclaw config list --providers

# Test specific provider connectivity
$ openclaw provider test anthropic --model claude-3-5-sonnet

# View supported models for a provider
$ openclaw models list --provider anthropic

# Validate config.yaml
$ openclaw config validate

Evidencia y fuentes

Esta guía de solución de problemas fue sintetizada automáticamente por la tubería de inteligencia de FixClaw a partir de las discusiones de la comunidad.