-
Notifications
You must be signed in to change notification settings - Fork 2.6k
fix: improve error handling for partial message control flow (fixes #7312) #7315
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -104,6 +104,14 @@ import { maybeRemoveImageBlocks } from "../../api/transform/image-cleaning" | |||||||||||||||||||||||
| import { restoreTodoListForTask } from "../tools/updateTodoListTool" | ||||||||||||||||||||||||
| import { AutoApprovalHandler } from "./AutoApprovalHandler" | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| // Custom error class for expected control flow in partial message handling | ||||||||||||||||||||||||
| class PartialMessageControlFlowError extends Error { | ||||||||||||||||||||||||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider exporting this error class for use in other modules that might need to distinguish between expected control flow and actual errors. This would improve error handling consistency across the codebase. |
||||||||||||||||||||||||
| constructor(message: string) { | ||||||||||||||||||||||||
| super(message) | ||||||||||||||||||||||||
| this.name = "PartialMessageControlFlowError" | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The error messages use slightly different formats. Consider standardizing them for consistency. Also, instead of hardcoding messages in three places, consider using static methods or constants:
Suggested change
Then use like: |
||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| const MAX_EXPONENTIAL_BACKOFF_SECONDS = 600 // 10 minutes | ||||||||||||||||||||||||
| const DEFAULT_USAGE_COLLECTION_TIMEOUT_MS = 5000 // 5 seconds | ||||||||||||||||||||||||
| const FORCED_CONTEXT_REDUCTION_PERCENT = 75 // Keep 75% of context (remove 25%) on context window errors | ||||||||||||||||||||||||
|
|
@@ -686,14 +694,18 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike { | |||||||||||||||||||||||
| // saves, and only post parts of partial message instead of | ||||||||||||||||||||||||
| // whole array in new listener. | ||||||||||||||||||||||||
| this.updateClineMessage(lastMessage) | ||||||||||||||||||||||||
| throw new Error("Current ask promise was ignored (#1)") | ||||||||||||||||||||||||
| // This is expected behavior during partial message updates | ||||||||||||||||||||||||
| // Return early instead of throwing to avoid confusing error logs | ||||||||||||||||||||||||
| throw new PartialMessageControlFlowError("Partial message update - expected behavior") | ||||||||||||||||||||||||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good use of descriptive error messages that clearly indicate this is expected behavior. This will help both developers and AI models understand these aren't actual failures. |
||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||
| // This is a new partial message, so add it with partial | ||||||||||||||||||||||||
| // state. | ||||||||||||||||||||||||
| askTs = Date.now() | ||||||||||||||||||||||||
| this.lastMessageTs = askTs | ||||||||||||||||||||||||
| await this.addToClineMessages({ ts: askTs, type: "ask", ask: type, text, partial, isProtected }) | ||||||||||||||||||||||||
| throw new Error("Current ask promise was ignored (#2)") | ||||||||||||||||||||||||
| // This is expected behavior when creating a new partial message | ||||||||||||||||||||||||
| // Return early instead of throwing to avoid confusing error logs | ||||||||||||||||||||||||
| throw new PartialMessageControlFlowError("New partial message - expected behavior") | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||
| if (isUpdatingPreviousPartial) { | ||||||||||||||||||||||||
|
|
@@ -797,7 +809,9 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike { | |||||||||||||||||||||||
| // Could happen if we send multiple asks in a row i.e. with | ||||||||||||||||||||||||
| // command_output. It's important that when we know an ask could | ||||||||||||||||||||||||
| // fail, it is handled gracefully. | ||||||||||||||||||||||||
| throw new Error("Current ask promise was ignored") | ||||||||||||||||||||||||
| // This can happen when multiple asks are sent in sequence | ||||||||||||||||||||||||
| // It's a normal part of the control flow, not an error | ||||||||||||||||||||||||
| throw new PartialMessageControlFlowError("Ask promise superseded - expected behavior") | ||||||||||||||||||||||||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. While the PR mentions all tests pass, it would be good to add specific test coverage for this error handling to ensure callers using |
||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| const result = { response: this.askResponse!, text: this.askResponseText, images: this.askResponseImages } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
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.
Consider adding JSDoc documentation to this class to make it more discoverable and explain when it should be used vs regular errors: