linshenkx/prompt-optimizer · error · APIError

Unexpected API response format

Error message

Unexpected API response format

What it means

Thrown by AnthropicAdapter.getModelsAsync when the response body from the /v1/models endpoint does not match the expected shape (a JSON object with a data array). The adapter successfully got an HTTP response but could not parse any models out of it, so it aborts with a generic format error instead of returning garbage.

Source

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

      // 检查返回格式
      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}`)
      }

      // API 错误处理
      if (error.status) {
        throw new APIError(`Anthropic API error (${error.status}): ${error.message}`)
      }

      // 其他错误
      throw error

View on GitHub (pinned to 3e677b1d9f)

Solutions

  1. Verify the base URL is the real Anthropic API (https://api.anthropic.com) or a gateway that faithfully implements GET /v1/models
  2. curl the endpoint manually: curl -H "x-api-key: $KEY" $BASE_URL/v1/models and inspect the JSON shape
  3. If using a proxy, fix or upgrade it so { data: [...] } is returned
  4. Handle the APIError in the caller and surface a fallback static model list

Example fix

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

// after
let models
try {
  models = await adapter.getModelsAsync()
} catch (e) {
  if (e instanceof APIError && /Unexpected API response format/.test(e.message)) {
    models = FALLBACK_ANTHROPIC_MODELS
  } else throw e
}
Defensive patterns

Strategy: try-catch

Validate before calling

null

Type guard

function isAnthropicModelsPayload(d: unknown): d is { data: unknown[] } {
  return !!d && typeof d === 'object' && Array.isArray((d as any).data)
}

Try / catch

try {
  const models = await adapter.getModelsAsync()
} catch (e) {
  if (e instanceof APIError && e.message === 'Unexpected API response format') {
    // verify endpoint manually, fall back to static model list
  } else throw e
}

Prevention

When it happens

Trigger: Calling getModelsAsync() against an endpoint that returns non-JSON or a different schema: a proxy/gateway HTML error page with 200 status, a base URL pointing at an OpenAI-compatible server rather than Anthropic's API, or an API version that changed the models payload.

Common situations: Misconfigured baseURL (e.g. https://api.openai.com with an Anthropic key), self-hosted gateways (one-api, litellm) that don't implement GET /v1/models the Anthropic way, corporate proxies returning HTML login pages.

Related errors


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