{"record":{"id":"5665e4811d9f6caf","repo":"linshenkx/prompt-optimizer","slug":"api-returned-empty-model-list","errorCode":null,"errorMessage":"API returned empty model list","messagePattern":"API returned empty model list","errorType":"exception","errorClass":"APIError","httpStatus":null,"severity":"error","filePath":"packages/core/src/services/llm/adapters/anthropic-adapter.ts","lineNumber":131,"sourceCode":"   */\n  public async getModelsAsync(config: TextModelConfig): Promise<TextModel[]> {\n    const client = this.createClient(config)\n\n    try {\n      const response = await client.models.list()\n\n      // 检查返回格式\n      if (response && response.data && Array.isArray(response.data)) {\n        const models = response.data\n          .map((model: any) => {\n            // 使用 buildDefaultModel 为每个模型 ID 创建 TextModel 对象\n            // Anthropic API 返回的 model 对象包含: id, name, version, capabilities\n            return this.buildDefaultModel(model.id)\n          })\n          .sort((a, b) => a.id.localeCompare(b.id))\n\n        if (models.length === 0) {\n          throw new APIError('API returned empty model list')\n        }\n\n        console.log(`[AnthropicAdapter] Successfully fetched ${models.length} models`)\n        return models\n      }\n\n      throw new APIError('Unexpected API response format')\n    } catch (error: any) {\n      console.error('[AnthropicAdapter] Failed to fetch models:', error)\n\n      // 连接错误处理（包括跨域检测）\n      if (error.message && (error.message.includes('Failed to fetch') ||\n          error.message.includes('NetworkError') ||\n          error.message.includes('ECONNREFUSED') ||\n          error.message.includes('CORS'))) {\n        throw new APIError(`Network error: ${error.message}`)\n      }\n","sourceCodeStart":113,"sourceCodeEnd":149,"githubUrl":"https://github.com/linshenkx/prompt-optimizer/blob/3e677b1d9f7e0493c142c175560531e7ae786dce/packages/core/src/services/llm/adapters/anthropic-adapter.ts#L113-L149","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Log the raw API response body to verify the expected { data: [{ id, ... }] } shape","Update the adapter or SDK to the latest version if Anthropic changed the response schema","If using a proxy/gateway, confirm it forwards the models endpoint unmodified","Fall back to a hardcoded default model list when this error is caught"],"exampleFix":"// before\nconst models = await adapter.getModelsAsync()\n\n// after\nlet models\ntry {\n  models = await adapter.getModelsAsync()\n} catch (e) {\n  if (e instanceof APIError && /empty model list/.test(e.message)) {\n    models = [adapter.buildDefaultModel('claude-3-5-sonnet')]\n  } else throw e\n}","handlingStrategy":"fallback","validationCode":"null","typeGuard":"null","tryCatchPattern":"try {\n  models = await adapter.getModelsAsync()\n} catch (e) {\n  if (e instanceof APIError && e.message.includes('empty model list')) {\n    models = [/* hardcoded fallback models */]\n  } else {\n    throw e\n  }\n}","preventionTips":["Log raw provider responses to detect schema drift early","Pin the adapter/SDK version and test getModelsAsync after upgrades","Maintain a hardcoded fallback model list for critical paths"],"tags":["anthropic","models","api-error","empty-response"],"backgroundTag":"empty-model-list-response","analyzedSha":"3e677b1d9f7e0493c142c175560531e7ae786dce","analyzedAt":"2026-08-27T21:29:16.709Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}