linshenkx/prompt-optimizer · error · APIError
Failed to send message: ${error.message}
Error message
Failed to send message: ${error.message} What it means
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.
Source
Thrown at packages/core/src/services/llm/service.ts:108
throw new RequestConfigError(`Model ${provider} not found`);
}
this.validateModelConfig(modelConfig);
this.validateMessages(messages);
// 通过 Registry 获取 Adapter
const adapter = this.registry.getAdapter(modelConfig.providerMeta.id);
const runtimeConfig = this.prepareRuntimeConfig(modelConfig);
// 使用 Adapter 发送消息
return await adapter.sendMessage(messages, runtimeConfig);
} catch (error: any) {
if (error instanceof RequestConfigError || error instanceof APIError) {
throw error;
}
throw new APIError(`Failed to send message: ${error.message}`);
}
}
/**
* 发送消息(传统格式,只返回主要内容)
*/
async sendMessage(messages: Message[], provider: string): Promise<string> {
const response = await this.sendMessageStructured(messages, provider);
// 只返回主要内容,不包含推理内容
// 如果需要推理内容,请使用 sendMessageStructured 方法
return response.content;
}
/**
* 发送消息(流式,支持结构化和传统格式)
*/
async sendMessageStream(View on GitHub (pinned to 3e677b1d9f)
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
Example fix
// before
try { await llm.sendMessageStructured(msgs, 'openai'); }
catch (e) { console.log(String(e)); } // 'Failed to send message: fetch failed' — cause hidden
// after
try { await llm.sendMessageStructured(msgs, 'openai'); }
catch (e) {
console.error(e instanceof APIError ? e.message : e);
if (e instanceof Error && e.message.includes('Failed to send message')) {
// inspect e.cause or network state before retrying
}
} Defensive patterns
Strategy: try-catch
Validate before calling
null
Type guard
null
Try / catch
try {
await llm.sendMessageStructured(msgs, 'openai');
} catch (e) {
if (e instanceof APIError) { /* inspect message/cause; retry only transient network causes with backoff */ }
else throw e;
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Connection test failed: ${error.message}
- error instanceof Error ? error.message : String(error)
- Evaluation mode configuration must not be empty.
- Workspace prompt must not be empty.
- formatExecutionErrorMessage(error)
AI-assisted analysis of linshenkx/prompt-optimizer@3e677b1d9f (2026-08-27).
Data as JSON: /api/errors/3a052a07da7c32ef.
Report an issue: GitHub.