linshenkx/prompt-optimizer · error · APIError

API returned empty model list

Error message

API returned empty model list

What it means

Thrown by AnthropicAdapter.getModelsAsync when the Anthropic models endpoint responds successfully but maps to zero models (empty data array). The adapter treats an empty model list as an API-level error (APIError) rather than returning [], because an authenticated Anthropic account should always expose at least the default models.

Source

Thrown at packages/core/src/services/llm/adapters/anthropic-adapter.ts:131

   */
  public async getModelsAsync(config: TextModelConfig): Promise<TextModel[]> {
    const client = this.createClient(config)

    try {
      const response = await client.models.list()

      // 检查返回格式
      if (response && response.data && Array.isArray(response.data)) {
        const models = response.data
          .map((model: any) => {
            // 使用 buildDefaultModel 为每个模型 ID 创建 TextModel 对象
            // Anthropic API 返回的 model 对象包含: id, name, version, capabilities
            return this.buildDefaultModel(model.id)
          })
          .sort((a, b) => a.id.localeCompare(b.id))

        if (models.length === 0) {
          throw new APIError('API returned empty model list')
        }

        console.log(`[AnthropicAdapter] Successfully fetched ${models.length} models`)
        return models
      }

      throw new APIError('Unexpected API response format')
    } catch (error: any) {
      console.error('[AnthropicAdapter] Failed to fetch models:', error)

      // 连接错误处理(包括跨域检测)
      if (error.message && (error.message.includes('Failed to fetch') ||
          error.message.includes('NetworkError') ||
          error.message.includes('ECONNREFUSED') ||
          error.message.includes('CORS'))) {
        throw new APIError(`Network error: ${error.message}`)
      }

View on GitHub (pinned to 3e677b1d9f)

Solutions

  1. Log the raw API response body to verify the expected { data: [{ id, ... }] } shape
  2. Update the adapter or SDK to the latest version if Anthropic changed the response schema
  3. If using a proxy/gateway, confirm it forwards the models endpoint unmodified
  4. Fall back to a hardcoded default model list when this error is caught

Example fix

// before
const models = await adapter.getModelsAsync()

// after
let models
try {
  models = await adapter.getModelsAsync()
} catch (e) {
  if (e instanceof APIError && /empty model list/.test(e.message)) {
    models = [adapter.buildDefaultModel('claude-3-5-sonnet')]
  } else throw e
}
Defensive patterns

Strategy: fallback

Validate before calling

null

Type guard

null

Try / catch

try {
  models = await adapter.getModelsAsync()
} catch (e) {
  if (e instanceof APIError && e.message.includes('empty model list')) {
    models = [/* hardcoded fallback models */]
  } else {
    throw e
  }
}

Prevention

When it happens

Trigger: Calling getModelsAsync when the API response's data array is empty after mapping/filtering — e.g. an unexpected response schema where model.id extraction yields nothing, a filtered proxy/enterprise endpoint, or a malformed 200 response.

Common situations: API response shape changed after an Anthropic API version bump (fields renamed, so mapping produces nothing); requests routed through a gateway that returns an empty list; a broken interceptor stripping the data field.

Related errors


AI-assisted analysis of linshenkx/prompt-optimizer@3e677b1d9f (2026-08-27). Data as JSON: /api/errors/5665e4811d9f6caf. Report an issue: GitHub.