linshenkx/prompt-optimizer · error · APIError
No valid response received
Error message
No valid response received
What it means
The choices array existed but choices[0].message is null/undefined — e.g. the provider returned a choice with only finish_reason or a tool_call envelope without a message object — so the adapter rejects the response as invalid.
Source
Thrown at packages/core/src/services/llm/adapters/openai-adapter.ts:1153
protected async parseCompletionResponse(response: any, modelId: string): Promise<LLMResponse> {
// 处理原始 SSE 字符串响应(某些 API 返回未解析的 SSE 格式)
if (typeof response === 'string') {
return this.parseSSEResponse(response, modelId)
}
// 检测是否为流式响应(某些 API 强制返回流式响应)
if (this.isStreamResponse(response)) {
return await this.consumeStreamResponse(response as AsyncIterable<any>, modelId)
}
// 处理响应中的 reasoning_content 和普通 content
if (!response.choices || response.choices.length === 0) {
throw new APIError('API returned invalid response: choices is empty or missing')
}
const choice = response.choices[0]
if (!choice?.message) {
throw new APIError('No valid response received')
}
let content = choice.message.content || ''
let reasoning = ''
// 处理推理内容(如果存在)
// SiliconFlow 等提供商在 choice.message 中并列提供 reasoning_content 字段
if ((choice.message as any).reasoning_content) {
reasoning = (choice.message as any).reasoning_content
} else {
// 检测并分离content中的think标签
const processed = this.processThinkTags(content)
content = processed.content
reasoning = processed.reasoning || ''
}
return {
content: content,View on GitHub (pinned to 3e677b1d9f)
Solutions
- Inspect the raw choice object (finish_reason often explains it)
- If finish_reason is content_filter, adjust prompt/inputs
- Fix or upgrade the compatible server to include a message object
- Handle gracefully with a retry or user-facing notice
Example fix
// before
const r = await openai.chat.completions.create({...})
const text = r.choices[0].message.content
// after
const r = await openai.chat.completions.create({...})
const c = r.choices?.[0]
if (!c?.message) throw new Error(`No valid response received (finish_reason=${c?.finish_reason})`)
const text = c.message.content ?? '' Defensive patterns
Strategy: validation
Validate before calling
null
Type guard
function hasValidMessage(r: unknown): boolean {
const c = (r as any)?.choices?.[0]
return !!c && typeof c.message === 'object' && c.message !== null
} Try / catch
try { return await adapter.sendMessage(msgs) }
catch (e) {
if (e instanceof APIError && e.message === 'No valid response received') {
if (lastFinishReason === 'content_filter') return regenerateWithSaferPrompt()
return retryOnce(() => adapter.sendMessage(msgs))
}
throw e
} Prevention
- Inspect finish_reason on filtered/empty completions
- Upgrade gateways that drop the message field
- Handle null content from content filters explicitly
When it happens
Trigger: Malformed first choice from an OpenAI-compatible server, responses where content is null after content filtering, or gateway bugs dropping the message field.
Common situations: Content-filtered completions (message null with finish_reason:'content_filter'), half-implemented compatible servers, race-y streaming-to-nonstreaming conversions.
Related errors
- API returned invalid response: choices is empty or missing
- Unexpected API response format
- UNSUPPORTED_TEST_TYPE
- Unexpected API response format
- Cloudflare model search returned an unexpected response form
AI-assisted analysis of linshenkx/prompt-optimizer@3e677b1d9f (2026-08-27).
Data as JSON: /api/errors/d301e92e7b9d6545.
Report an issue: GitHub.