{"record":{"id":"3a052a07da7c32ef","repo":"linshenkx/prompt-optimizer","slug":"failed-to-send-message-error-message","errorCode":null,"errorMessage":"Failed to send message: ${error.message}","messagePattern":"Failed to send message: (.+?)","errorType":"exception","errorClass":"APIError","httpStatus":null,"severity":"error","filePath":"packages/core/src/services/llm/service.ts","lineNumber":108,"sourceCode":"        throw new RequestConfigError(`Model ${provider} not found`);\n      }\n\n      this.validateModelConfig(modelConfig);\n      this.validateMessages(messages);\n\n      // 通过 Registry 获取 Adapter\n      const adapter = this.registry.getAdapter(modelConfig.providerMeta.id);\n\n      const runtimeConfig = this.prepareRuntimeConfig(modelConfig);\n\n      // 使用 Adapter 发送消息\n      return await adapter.sendMessage(messages, runtimeConfig);\n\n    } catch (error: any) {\n      if (error instanceof RequestConfigError || error instanceof APIError) {\n        throw error;\n      }\n      throw new APIError(`Failed to send message: ${error.message}`);\n    }\n  }\n\n  /**\n   * 发送消息（传统格式，只返回主要内容）\n   */\n  async sendMessage(messages: Message[], provider: string): Promise<string> {\n    const response = await this.sendMessageStructured(messages, provider);\n    \n    // 只返回主要内容，不包含推理内容\n    // 如果需要推理内容，请使用 sendMessageStructured 方法\n    return response.content;\n  }\n\n  /**\n   * 发送消息（流式,支持结构化和传统格式）\n   */\n  async sendMessageStream(","sourceCodeStart":90,"sourceCodeEnd":126,"githubUrl":"https://github.com/linshenkx/prompt-optimizer/blob/3e677b1d9f7e0493c142c175560531e7ae786dce/packages/core/src/services/llm/service.ts#L90-L126","documentation":"Wrapped APIError thrown by sendMessageStructured when any unexpected exception escapes the request pipeline that is not already a RequestConfigError or APIError. The original message is appended ('Failed to send message: <cause>'). The real cause can be adapter construction, network I/O, or response parsing inside adapter.sendMessage.","triggerScenarios":"Any non-RequestConfigError/non-APIError thrown inside sendMessageStructured: network failures (ECONNREFUSED, DNS), malformed request payloads, SDK exceptions from the provider client, or bugs in a custom adapter's sendMessage implementation.","commonSituations":"Provider endpoint unreachable or proxy misconfigured; invalid API key causing the underlying SDK to throw its own error type; custom adapters registered in the registry throwing raw Errors; provider response format changes breaking response parsing.","solutions":["Inspect error.cause / the appended message to identify the underlying exception before assuming an LLM-service bug","If it's a network issue, verify base URL, proxy env vars, and connectivity to the provider endpoint","If a custom adapter, ensure adapter.sendMessage maps its failures to APIError and log the original stack","Retry with backoff for transient network causes; APIError may be retried only if the cause was transient"],"exampleFix":"// before\ntry { await llm.sendMessageStructured(msgs, 'openai'); }\ncatch (e) { console.log(String(e)); } // 'Failed to send message: fetch failed' — cause hidden\n\n// after\ntry { await llm.sendMessageStructured(msgs, 'openai'); }\ncatch (e) {\n  console.error(e instanceof APIError ? e.message : e);\n  if (e instanceof Error && e.message.includes('Failed to send message')) {\n    // inspect e.cause or network state before retrying\n  }\n}","handlingStrategy":"try-catch","validationCode":"null","typeGuard":"null","tryCatchPattern":"try {\n  await llm.sendMessageStructured(msgs, 'openai');\n} catch (e) {\n  if (e instanceof APIError) { /* inspect message/cause; retry only transient network causes with backoff */ }\n  else throw e;\n}","preventionTips":["Log error.cause, not just the wrapped message, to find the real failure","Verify endpoint/proxy/API key before assuming a service bug","Wrap custom adapters so they throw APIError with the original error attached","Add retry-with-backoff for transient network causes"],"tags":["llm","network","adapter","wrapper-error"],"backgroundTag":"llm-api-request-failed","analyzedSha":"3e677b1d9f7e0493c142c175560531e7ae786dce","analyzedAt":"2026-08-27T21:29:16.709Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}