April 15, 2026 • バージョン: v2026.4.14-beta.1

ダッシュボードのモデル選択ドロップダウンに未構成プロバイダーのモデルが表示される

OpenClaw ダッシュボードのAgentモデル選択ドロップダウンでは、プロバイダーの設定状態に関係なく、対応のすべてのモデルが表示されます。これにより、利用不可のモデルを選択したユーザーに混乱が生じます。

🔍 症状

ユーザーから報告された動作

Dashboard(http://localhost:8080)にアクセスし、Agent Settingsに移動すると、Primary Modelドロップダウンに広範なモデルのリストが表示されます:

┌─────────────────────────────────────────────────────────┐
│  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                                  │
└─────────────────────────────────────────────────────────┘

失敗シナリオ

ユーザーが未設定のプロバイダー(例:anthropic/claude-opus-4-5)からのモデルを選択し、エージェントを保存または使用しようとすると:

$ 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.

技術的な症状

ブラウザコンソールで、ドロップダウンコンポーネントがsrc/models/supported-models.jsonからモデルを読み込み、プロバイダーの可用性を確認せずにレンダリングします:

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

🧠 原因

アーキテクチャ上の問題

Dashboardのモデル選択コンポーネント(src/components/ModelSelector.tsx)は、コンポーネントの初期化時に静的モデルレジストリからサポートされているモデルの完全なリストを読み込みます:

// 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
}

プロバイダーの可用性チェックの欠落

コンポーネントはgetConfiguredProviders()や同等のものを呼び出して、プロバイダーの可用性によってモデルをフィルタリングしません。モデルレジストリとプロバイダー設定は別々のデータドメインに存在し、統合されていません:

┌─────────────────────────────────┐
│  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          │
└─────────────────────────────────┘

データフローのギャップ

  1. ユーザーがDashboardを開くModelSelectorコンポーネントがマウント
  2. コンポーネントがすべてのモデルを取得getSupportedModels()が完了な静的リストを返す
  3. バックエンドへのAPI呼び出しなし → コンポーネントは/api/providers/statusをクエリしない
  4. ドロップダウンがすべてのモデルを表示 → 未設定のプロバイダーからのモデルも含む
  5. ユーザーが無効なモデルを選択 → 実行時にのみ런タイムエラーが発生

影響を受けるコードパス

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

🛠️ 解決手順

Option A: 設定済みプロバイダーでモデルをフィルタリング(推奨)

src/components/ModelSelector.tsxを変更して、プロバイダーの可用性に基づいてモデルをフィルタリングします:

// 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
}

Option B: 未設定のモデルに視覚的なインジケーターを追加

すべてのモデルの視認性を維持しながら視覚的な区別を行う場合:

// 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>
  );
}

Option C: バックエンド主導のフィルタリング

利用可能なモデルのみを返す新しいAPIエンドポイントを追加します:

// 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;

🧪 検証

検証手順

修正を適用した後、以下の方法で動作を確認します:

1. Dashboard UIの検証

# 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. 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. コンポーネントのユニットテスト

# 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. 統合テスト

# 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

終了コードの検証

# 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

⚠️ よくある落とし穴

処理が必要なエッジケース

  • プロバイダーが一つも設定されていない場合: ドロップダウンには「利用可能なモデルを表示するにはプロバイダーを設定してください」というメッセージとともに空の状態が表示される必要があります
  • セッション中にプロバイダーが設定された場合: ModelSelectorはフォーカス時またはウィンドウのフォーカスイベント時にプロバイダーリストを再取得する必要があります
  • プロバイダーのAPIキーが無効になった場合: モデルは表示されたままです(サーバー側のバリデーションがランタイムエラーを処理します)
  • 初期読み込み時の競合状態: プロバイダー設定の取得中はローディングスケルトンを表示します

環境固有の考慮事項

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

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

設定のよくある間違い

config内のprovider IDが正しくない:
# WRONG - provider ID mismatch
providers:
  anthropic_api:
    type: anthropic    # Should match model provider name

CORRECT

providers: anthropic: type: anthropic

必須フィールドの欠落:
# WRONG - missing api_key
providers:
  anthropic:
    type: anthropic
    # api_key is required

CORRECT

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

🔗 関連するエラー

関連する問題

  • ERR_PROVIDER_NOT_CONFIGURED: 未設定のプロバイダーからのモデルを使用しようとしたときに発生します。現在、UIレベルではなくランタイムに発生します。
  • ERR_API_KEY_INVALID: プロバイダーは設定されているが認証情報が無効です。configチェックは通過하지만認証に失敗するモデルのドロップダウン表示に関連します。
  • ERR_MODEL_NOT_FOUND: モデルID形式が変更されたがDashboardのモデルリストが古い場合に発生します。OpenClawのバージョンアップグレード後に発生する可能性があります。

過去の経緯

バージョン問題解決策
v2026.3.xプロバイダードロップダウンがconfigに関係なくすべてのプロバイダーを表示部分的な修正 - プロバイダーリストはフィルタリングされたが、モデルリストは未対応
v2026.2.xAPI認証情報がconfig.yamlにプレーンテキストで保存されていた暗号化のサポートを追加
v2026.1.x大きなモデルリストでモデル選択が応答しない仮想スクロールを追加

関連ドキュメント

デバッグコマンド

# 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

エビデンスとソース

このトラブルシューティングガイドは、FixClaw Intelligence パイプラインによってコミュニティの議論から自動的に合成されました。