mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-09-09 22:31:08 +00:00
fix: improve error handling for empty Claude Sonnet responses
- Add detailed logging for empty assistant responses - Provide more informative error messages with model/protocol info - Add specific detection for Claude Sonnet models with known issues - Improve retry logic for native protocol to handle user message cleanup - Better user guidance suggesting Claude Opus 4.1 as alternative Fixes #9525
This commit is contained in:
parent
d96f939dca
commit
de48190231
1 changed files with 41 additions and 7 deletions
|
|
@ -2749,6 +2749,19 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
|
|||
const hasTextContent = assistantMessage.length > 0
|
||||
const hasToolUses = this.assistantMessageContent.some((block) => block.type === "tool_use")
|
||||
|
||||
// Special check for Claude Sonnet models with known issues
|
||||
const modelId = this.api.getModel().id
|
||||
const isClaudeSonnet =
|
||||
modelId.includes("claude") && modelId.includes("sonnet") && !modelId.includes("opus")
|
||||
|
||||
if (!hasTextContent && !hasToolUses && isClaudeSonnet) {
|
||||
const protocol = resolveToolProtocol(this.apiConfiguration, this.api.getModel().info)
|
||||
console.warn(
|
||||
`[Task#${this.taskId}.${this.instanceId}] Claude Sonnet model (${modelId}) returned empty response with ${protocol} protocol. ` +
|
||||
`This is a known issue. Consider switching to Claude Opus 4.1 or adjusting tool protocol settings.`,
|
||||
)
|
||||
}
|
||||
|
||||
if (hasTextContent || hasToolUses) {
|
||||
// Display grounding sources to the user if they exist
|
||||
if (pendingGroundingSources.length > 0) {
|
||||
|
|
@ -2845,6 +2858,15 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
|
|||
// or tool_use content blocks from API which we should assume is
|
||||
// an error.
|
||||
|
||||
// Log detailed information for debugging
|
||||
const modelId = this.api.getModel().id
|
||||
const protocol = resolveToolProtocol(this.apiConfiguration, this.api.getModel().info)
|
||||
console.error(
|
||||
`[Task#${this.taskId}.${this.instanceId}] Empty assistant response detected. ` +
|
||||
`Model: ${modelId}, Protocol: ${protocol}, ` +
|
||||
`Retry attempt: ${currentItem.retryAttempt ?? 0}`,
|
||||
)
|
||||
|
||||
// IMPORTANT: For native tool protocol, we already added the user message to
|
||||
// apiConversationHistory at line 1876. Since the assistant failed to respond,
|
||||
// we need to remove that message before retrying to avoid having two consecutive
|
||||
|
|
@ -2866,7 +2888,9 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
|
|||
if (state?.autoApprovalEnabled && state?.alwaysApproveResubmit) {
|
||||
// Auto-retry with backoff - don't persist failure message when retrying
|
||||
const errorMsg =
|
||||
"Unexpected API Response: The language model did not provide any assistant messages. This may indicate an issue with the API or the model's output."
|
||||
`Unexpected API Response from ${modelId}: The language model did not provide any assistant messages. ` +
|
||||
`This may indicate an issue with the API or the model's output. ` +
|
||||
`Using ${protocol} protocol. Retrying...`
|
||||
|
||||
await this.backoffAndAnnounce(
|
||||
currentItem.retryAttempt ?? 0,
|
||||
|
|
@ -2894,20 +2918,29 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
|
|||
// Continue to retry the request
|
||||
continue
|
||||
} else {
|
||||
// Prompt the user for retry decision
|
||||
const { response } = await this.ask(
|
||||
"api_req_failed",
|
||||
"The model returned no assistant messages. This may indicate an issue with the API or the model's output.",
|
||||
)
|
||||
// Prompt the user for retry decision with more detailed error message
|
||||
const errorDetails =
|
||||
`The model ${modelId} returned no assistant messages using ${protocol} protocol. ` +
|
||||
`This may indicate an issue with the API or the model's output. ` +
|
||||
`Claude Opus 4.1 is known to work reliably. ` +
|
||||
`You may want to switch models or check your API configuration.`
|
||||
|
||||
const { response } = await this.ask("api_req_failed", errorDetails)
|
||||
|
||||
if (response === "yesButtonClicked") {
|
||||
await this.say("api_req_retried")
|
||||
|
||||
// Mark that user message might need to be re-added for native protocol
|
||||
const needsUserMessageReAdd = isNativeProtocol(
|
||||
resolveToolProtocol(this.apiConfiguration, this.api.getModel().info),
|
||||
)
|
||||
|
||||
// Push the same content back to retry
|
||||
stack.push({
|
||||
userContent: currentUserContent,
|
||||
includeFileDetails: false,
|
||||
retryAttempt: (currentItem.retryAttempt ?? 0) + 1,
|
||||
userMessageWasRemoved: needsUserMessageReAdd,
|
||||
})
|
||||
|
||||
// Continue to retry the request
|
||||
|
|
@ -2927,7 +2960,8 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
|
|||
|
||||
await this.say(
|
||||
"error",
|
||||
"Unexpected API Response: The language model did not provide any assistant messages. This may indicate an issue with the API or the model's output.",
|
||||
`Unexpected API Response from ${modelId}: The language model did not provide any assistant messages. ` +
|
||||
`This may indicate an issue with the API or the model's output when using ${protocol} protocol.`,
|
||||
)
|
||||
|
||||
await this.addToApiConversationHistory({
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue