-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Open
Description
Summary
After aborting an operation and continuing the conversation, the following error occurs:
Error in agent execution: Error: 400 -4316: messages.37: all messages must have non-empty content except for the optional final assistant message
Root Cause
When abort occurs during LLM streaming, an empty assistant message is created in conversation history:
First Agent Loop (Normal)
[
{"role": "system", "content": "..."},
{"role": "user", "content": "Question"}
]Second Agent Loop (After Abort)
[
{"role": "system", "content": "..."},
{"role": "user", "content": "Question"},
{"role": "assistant"}, // Empty content violates Claude API validation
{"role": "user", "content": "继续"}
]Technical Analysis
The issue occurs in llm-processor.ts createFinalEvents method:
if (content || currentToolCalls.length > 0) {
const assistantEvent = this.eventStream.createEvent('assistant_message', {
content: content, // Empty string when aborted
finishReason: finishReason,
// ...
});
}When NativeToolCallEngine.buildHistoricalAssistantMessage processes this:
const message: ChatCompletionMessageParam = {
role: 'assistant',
content: content, // Empty string violates Claude API
};Solution
Modify createFinalEvents in llm-processor.ts:
private createFinalEvents(
content: string,
rawContent: string,
currentToolCalls: ChatCompletionMessageToolCall[],
reasoningBuffer: string,
finishReason: string,
messageId?: string,
ttftMs?: number,
ttltMs?: number,
): void {
// Provide default content for aborted requests
let finalContent = content;
if (!content && finishReason === 'abort') {
finalContent = '[Request was aborted by user]';
}
if (finalContent || currentToolCalls.length > 0) {
const assistantEvent = this.eventStream.createEvent('assistant_message', {
content: finalContent,
rawContent: rawContent,
toolCalls: currentToolCalls.length > 0 ? currentToolCalls : undefined,
finishReason: finishReason,
messageId: messageId,
ttftMs: ttftMs,
ttltMs: ttltMs,
});
this.eventStream.sendEvent(assistantEvent);
}
}Benefits:
- Maintains conversation continuity
- Provides meaningful context to LLM
- Fixes API validation error
- Minimal code change
Metadata
Metadata
Assignees
Labels
No labels