{"record":{"id":"4e60d3a82d8ab1fe","repo":"linshenkx/prompt-optimizer","slug":"network-error-error-message","errorCode":null,"errorMessage":"Network error: ${error.message}","messagePattern":"Network error: (.+?)","errorType":"exception","errorClass":"APIError","httpStatus":null,"severity":"error","filePath":"packages/core/src/services/llm/adapters/anthropic-adapter.ts","lineNumber":147,"sourceCode":"\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\n      // API 错误处理\n      if (error.status) {\n        throw new APIError(`Anthropic API error (${error.status}): ${error.message}`)\n      }\n\n      // 其他错误\n      throw error\n    }\n  }\n\n  // ===== 参数定义（用于buildDefaultModel） =====\n\n  /**\n   * 获取参数定义\n   */\n  protected getParameterDefinitions(modelId: string): readonly ParameterDefinition[] {","sourceCodeStart":129,"sourceCodeEnd":165,"githubUrl":"https://github.com/linshenkx/prompt-optimizer/blob/3e677b1d9f7e0493c142c175560531e7ae786dce/packages/core/src/services/llm/adapters/anthropic-adapter.ts#L129-L165","documentation":"The fetch to Anthropic's models endpoint failed at the network level (message contains 'Failed to fetch', 'NetworkError', 'ECONNREFUSED', or 'CORS') and the adapter re-wraps it as an APIError prefixed with 'Network error:'. This is a browser/runtime connectivity problem, not an Anthropic-side API error.","triggerScenarios":"Running getModelsAsync() in a browser where the target host is unreachable, CORS headers are missing on a self-hosted proxy, the service is down (ECONNREFUSED on localhost), or a firewall/VPN blocks api.anthropic.com.","commonSituations":"Calling the Anthropic API directly from a web app (CORS is not allowed by Anthropic), local LLM gateway not running on the configured port, corporate proxy interference, offline development.","solutions":["If running in a browser, route requests through a server-side proxy — Anthropic's API does not send CORS headers","Check the gateway/local service is up: curl $BASE_URL/v1/models from the same machine","Ensure the base URL scheme/port are correct (https vs http, right port) and no VPN/firewall blocks it","For self-hosted proxies, enable CORS headers for your app origin"],"exampleFix":"// before\nconst models = await adapter.getModelsAsync()\n\n// after\nconst models = await withRetry(\n  () => adapter.getModelsAsync(),\n  { retries: 2, isRetryable: (e) => e instanceof APIError && e.message.startsWith('Network error') }\n)","handlingStrategy":"retry","validationCode":"async function canReach(url: string) {\n  try { await fetch(url, { method: 'HEAD', mode: 'no-cors' }); return true }\n  catch { return false }\n}","typeGuard":"function isNetworkError(e: unknown): e is APIError {\n  return e instanceof APIError && e.message.startsWith('Network error')\n}","tryCatchPattern":"try { models = await adapter.getModelsAsync() }\ncatch (e) {\n  if (isNetworkError(e)) return withBackoff(() => adapter.getModelsAsync(), 3)\n  throw e\n}","preventionTips":["Route browser calls through a same-origin server proxy","Ensure local gateways are running before the app starts","Add health checks for configured endpoints"],"tags":["network","cors","fetch","anthropic"],"backgroundTag":"fetch-network-error","analyzedSha":"3e677b1d9f7e0493c142c175560531e7ae786dce","analyzedAt":"2026-08-27T21:29:16.709Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}