From feb2fa8443c7167ed8db9ea73dadfb7765605809 Mon Sep 17 00:00:00 2001 From: Daniel <57051444+daniel-lxs@users.noreply.github.com> Date: Fri, 13 Jun 2025 19:09:04 -0500 Subject: [PATCH] Fix multi-file diff error handling and UI feedback (#4674) fix: improve multi-file diff error handling and UI feedback - Fix nested array issue in multi-file-search-replace strategy - Consolidate diff error reporting to single message - Fix infinite spinner on single file diff failures --- .../strategies/multi-file-search-replace.ts | 8 +++++++- src/core/tools/multiApplyDiffTool.ts | 20 +++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/core/diff/strategies/multi-file-search-replace.ts b/src/core/diff/strategies/multi-file-search-replace.ts index 57503da5f4..d35f32685e 100644 --- a/src/core/diff/strategies/multi-file-search-replace.ts +++ b/src/core/diff/strategies/multi-file-search-replace.ts @@ -410,7 +410,13 @@ Each file requires its own path, start_line, and diff elements. resultContent = singleResult.content successCount++ } else { - allFailParts.push(singleResult) + // If singleResult has failParts, push those directly to avoid nesting + if (singleResult.failParts && singleResult.failParts.length > 0) { + allFailParts.push(...singleResult.failParts) + } else { + // Otherwise push the single result itself + allFailParts.push(singleResult) + } } } diff --git a/src/core/tools/multiApplyDiffTool.ts b/src/core/tools/multiApplyDiffTool.ts index 8a75d58c5a..a80075e10f 100644 --- a/src/core/tools/multiApplyDiffTool.ts +++ b/src/core/tools/multiApplyDiffTool.ts @@ -220,6 +220,7 @@ Original error: ${errorMessage}` try { // First validate all files and prepare for batch approval const operationsToApprove: OperationResult[] = [] + const allDiffErrors: string[] = [] // Collect all diff errors for (const operation of operations) { const { path: relPath, diff: diffItems } = operation @@ -435,6 +436,9 @@ Original error: ${errorMessage}` continue } + // Collect error for later reporting + allDiffErrors.push(`${relPath} - Diff ${i + 1}: ${failPart.error}`) + const errorDetails = failPart.details ? JSON.stringify(failPart.details, null, 2) : "" formattedError += ` Diff ${i + 1} failed for file: ${relPath} @@ -479,6 +483,17 @@ ${errorDetails ? `\nTechnical details:\n${errorDetails}\n` : ""} } cline.recordToolError("apply_diff", formattedError) results.push(formattedError) + + // For single file operations, we need to send a complete message to stop the spinner + if (operationsToApprove.length === 1) { + const sharedMessageProps: ClineSayTool = { + tool: "appliedDiff", + path: getReadablePath(cline.cwd, relPath), + diff: diffItems.map((item) => item.content).join("\n\n"), + } + // Send a complete message (partial: false) to update the UI and stop the spinner + await cline.ask("tool", JSON.stringify(sharedMessageProps), false).catch(() => {}) + } } continue } @@ -571,6 +586,11 @@ ${errorDetails ? `\nTechnical details:\n${errorDetails}\n` : ""} results.push(...filteredOperationErrors) } + // Report all diff errors at once if any + if (allDiffErrors.length > 0) { + await cline.say("diff_error", allDiffErrors.join("\n")) + } + // Push the final result combining all operation results pushToolResult(results.join("\n\n")) return