-
Notifications
You must be signed in to change notification settings - Fork 2.5k
fix: improve XML parsing error handling for read_file tool #7802
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 | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -131,11 +131,21 @@ export async function readFileTool( | |||||||||
| const parsed = parseXml(argsXmlTag) as any | ||||||||||
| const files = Array.isArray(parsed.file) ? parsed.file : [parsed.file].filter(Boolean) | ||||||||||
|
|
||||||||||
| // Track invalid entries for better error reporting | ||||||||||
| const invalidEntries: string[] = [] | ||||||||||
|
|
||||||||||
| for (const file of files) { | ||||||||||
| if (!file.path) continue // Skip if no path in a file entry | ||||||||||
| // Check if path exists and is not empty after trimming | ||||||||||
| const filePath = typeof file.path === "string" ? file.path.trim() : file.path | ||||||||||
|
|
||||||||||
| if (!filePath) { | ||||||||||
| // Track this invalid entry | ||||||||||
| invalidEntries.push(JSON.stringify(file).substring(0, 100)) | ||||||||||
|
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. Performance consideration: For large malformed XML, collecting up to 100 characters of each invalid entry could accumulate unnecessary data. Consider limiting to the first 3 invalid entries:
Suggested change
|
||||||||||
| continue // Skip if no path in a file entry | ||||||||||
| } | ||||||||||
|
|
||||||||||
| const fileEntry: FileEntry = { | ||||||||||
| path: file.path, | ||||||||||
| path: filePath, | ||||||||||
| lineRanges: [], | ||||||||||
| } | ||||||||||
|
|
||||||||||
|
|
@@ -153,8 +163,16 @@ export async function readFileTool( | |||||||||
| } | ||||||||||
| fileEntries.push(fileEntry) | ||||||||||
| } | ||||||||||
|
|
||||||||||
| // If we had invalid entries but no valid ones, provide a helpful error | ||||||||||
| if (fileEntries.length === 0 && invalidEntries.length > 0) { | ||||||||||
| const errorMessage = `No valid file paths found in read_file args. Invalid entries: ${invalidEntries.join(", ")}. Ensure each <file> element contains a non-empty <path> element.` | ||||||||||
|
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 standardizing error message formats for consistency. We have "No valid file paths found" here and "Failed to parse read_file XML args" below. A consistent format would improve the user experience. |
||||||||||
| await handleError("parsing read_file args", new Error(errorMessage)) | ||||||||||
| pushToolResult(`<files><error>${errorMessage}</error></files>`) | ||||||||||
| return | ||||||||||
| } | ||||||||||
| } catch (error) { | ||||||||||
| const errorMessage = `Failed to parse read_file XML args: ${error instanceof Error ? error.message : String(error)}` | ||||||||||
| const errorMessage = `Failed to parse read_file XML args: ${error instanceof Error ? error.message : String(error)}. Expected format: <file><path>filepath</path></file>` | ||||||||||
| await handleError("parsing read_file args", new Error(errorMessage)) | ||||||||||
| pushToolResult(`<files><error>${errorMessage}</error></files>`) | ||||||||||
| return | ||||||||||
|
|
@@ -186,7 +204,10 @@ export async function readFileTool( | |||||||||
| if (fileEntries.length === 0) { | ||||||||||
| cline.consecutiveMistakeCount++ | ||||||||||
| cline.recordToolError("read_file") | ||||||||||
| const errorMsg = await cline.sayAndCreateMissingParamError("read_file", "args (containing valid file paths)") | ||||||||||
| const errorMsg = await cline.sayAndCreateMissingParamError( | ||||||||||
| "read_file", | ||||||||||
| "args with valid file paths. Expected format: <args><file><path>filepath</path></file></args>", | ||||||||||
|
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. Is this intentional? The error message mentions line_range in the documentation hint, but based on the tests, line_range isn't actually a supported parameter for the read_file tool. Could we clarify this in the tool documentation to avoid confusion? |
||||||||||
| ) | ||||||||||
| pushToolResult(`<files><error>${errorMsg}</error></files>`) | ||||||||||
| return | ||||||||||
| } | ||||||||||
|
|
||||||||||
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.
Great test coverage! Consider adding one more test that combines whitespace issues with multiple files where some have valid paths and others have empty paths after trimming. This would test the mixed scenario comprehensively.