-
Notifications
You must be signed in to change notification settings - Fork 2.6k
fix: prevent conversation history corruption when cancelling during response #8154
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…esponse - Add validation in abortTask to skip saving messages during active streaming - Add empty array checks in save methods to prevent corruption - Add validation in persistence layer to ensure valid message arrays - This fixes the race condition where cancelling during streaming could save empty arrays and wipe conversation history Fixes #8153
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewing my own code is like debugging in a mirror - everything looks backwards but the bugs are still mine.
| try { | ||
| // Validate that we have messages before saving to prevent corruption | ||
| if (!this.apiConversationHistory || this.apiConversationHistory.length === 0) { | ||
| console.warn( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this error handling approach intentional? The persistence layer throws errors for invalid input, but here we silently return. Consider making the validation behavior consistent across layers - either always throw for invalid data or always handle gracefully with logging.
| try { | ||
| // Validate that we have messages before saving to prevent corruption | ||
| if (!this.clineMessages || this.clineMessages.length === 0) { | ||
| console.warn(`[Task#saveClineMessages] Skipping save of empty Cline messages for task ${this.taskId}`) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same inconsistency here - we warn and return while the persistence layer throws. Should we standardize the approach?
| globalStoragePath: string | ||
| }) { | ||
| // Validate messages array to prevent saving empty arrays that could corrupt history | ||
| if (!messages || !Array.isArray(messages)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The validation logic here is nearly identical to saveTaskMessages. Could we extract this to a shared validation utility function to reduce duplication?
|
|
||
| export async function saveTaskMessages({ messages, taskId, globalStoragePath }: SaveTaskMessagesOptions) { | ||
| // Validate messages array to prevent saving empty arrays that could corrupt history | ||
| if (!messages || !Array.isArray(messages)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This duplicates the validation from apiMessages.ts. Consider extracting to a shared function.
| if (this.clineMessages && this.clineMessages.length > 0 && !this.isStreaming) { | ||
| await this.saveClineMessages() | ||
| } else if (this.isStreaming) { | ||
| console.log( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor: Using console.log here but console.warn in the save methods above. Should we use consistent log levels based on severity? Perhaps console.info for informational skips?
Summary
This PR fixes issue #8153 where cancelling a running response could corrupt the conversation history by saving empty arrays, making the chat unusable.
Problem
When users cancel a task during the model's "thinking/streaming" phase, a race condition could occur where:
this.abort = truesaveClineMessages()method is called during abortSolution
This fix implements a multi-layered defense approach:
1. Skip saving during active streaming
abortTask()to skip saving messages ifisStreamingis true2. Validation in save methods
saveApiConversationHistory()andsaveClineMessages()3. Persistence layer validation
saveApiMessages()andsaveTaskMessages()Testing
Review
The implementation was reviewed using the automated review tool with a 95% confidence score and PROCEED recommendation.
Fixes #8153
Important
Fixes conversation history corruption by preventing empty message arrays from being saved during task cancellation in
Task.ts.abortTask()inTask.ts.isStreamingis true to avoid race conditions.saveApiMessages()andsaveTaskMessages()to ensure messages are arrays and not empty.saveApiConversationHistory()andsaveClineMessages()inTask.tsto prevent corruption.This description was created by
for 7b22715. You can customize this summary. It will automatically update as commits are pushed.