Skip to content

Conversation

@dltechy
Copy link
Contributor

@dltechy dltechy commented Nov 29, 2025

Context

Some models incorrectly use the wrong XML format for their tool usage.
This behavior is very inconsistent and sometimes they do use the correct format.
This is most commonly experience with the dreaded error: "Kilo Code tried to use <tool> without value for required parameter 'path'"

Issues: #2273, #2347, #2855

Implementation

I found that the issue is due to some models using this format:

<[tool_name]>
  <args>
    <file>
      <path>.</path>
    </file>
  </args>
</[tool_name]>

This is the correct format for the read_file tool, but for some reason, some models keep trying to use it for other tools as well.

To fix this, I added a parser that specifically checks for the path parameter inside the args tag.
The parser logic was partly taken from the existing implementation of the read_file tool.
This would let Kilo Code parse any model's tool usage format no matter if it's correct or not.

Bonus: In case some models use an even further incorrect XML format, I also added handling for the missing <file> tag inside <args>:
xml~~ ~~<[tool_name]>~~ ~~ <args>~~ ~~ <path>.</path>~~ ~~ </args>~~ ~~</[tool_name]>~~ ~~

To ensure that existing working functionality is not affected, all tool calls use the default path parameter first.
Only if it doesn't exist, which would normally result in the tool use error, would the parser be called.
const relPath = params.path || parsePathFromArgsParam(params) || ""

I updated the implementation to be able to parse any parameter, not just path.

export function parseParamsFromArgs(
	args: string | undefined,
	paramNames: string[],
): Record<string, string | undefined> {

Usage

const args = parseParamsFromArgs(params.args, ["path", "diff"])
const relPath = params.path || args.path || ""
const diff = params.diff || args.diff || ""

But to make it work, I had to use regular string parsing to find the relevant tags instead of XML parsing.
Using a proper XML parser fails due to some params, like diff, that have symbols that XML is not happy with (e.g. <<<, >>>)

Note: I made the parser output undefined instead of an empty string ("") when no path params are actually found because some tool implementation checks for both undefined and "". Instead of trying to change their logic, I just made the parser output undefined and just used || "" for the tools that need an empty string.

Affected tools

  • apply_diff
  • codebase_search
  • delete_file
  • edit_file
  • insert_content
  • list_code_definition_names
  • list_files
  • read_file
  • search_files
  • write_to_file

Screenshots

before after
image image

How to Test

Due to the inconsistency of LLMs, this might be difficult to test.
But here's a basic test anyway:

  • Ask Kilo Code to use any file/directory handling tool
  • Check if the tool usage failed or not

To actually test that my implementation worked, I heavily utilized VSCode's breakpoints feature.
This let me actually know with certainty that the LLM used the "wrong" XML format, and that my fix indeed worked.
image

…or file/directory handling

Affected tools:
- apply_diff
- codebase_search
- delete_file
- edit_file
- insert_content
- list_code_definition_names
- list_files
- read_file
- search_files
- write_to_file
@changeset-bot
Copy link

changeset-bot bot commented Nov 29, 2025

🦋 Changeset detected

Latest commit: ee32737

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
kilo-code Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@dltechy dltechy changed the title Fix issue where some models used incorrect param format for file/directory handling Fix issue where some models used incorrect param format for file/directory handling tools Nov 29, 2025
Added fallback check for `parsed.path` in `parsePathFromArgsParam` function to improve reliability when extracting file paths from XML arguments.

This change ensures that when XML parsing returns a direct `path` property, it will be properly utilized, making the path extraction more resilient to different XML structures.
@mcowger
Copy link
Contributor

mcowger commented Nov 29, 2025

Good PR.

Couple suggestions

  1. Make sure you add kilocode_change markers
  2. Add a test or two.
  3. I think parsePathFromArgsParan() probably belongs in src/utils/pathUtils.ts

The old `parsePathFromArgsParam` used an XML parser to extract only the
`<path>` tag from <args>. This caused tools to break when parameters
contained diff markers (`<<<`, `>>>`) or other malformed
XML content, especially in apply-diff and code-edit operations.

This change replaces that logic with `parseParamsFromArgs`, a simple and
safe tag-scanning helper that:
- avoids XML parsing entirely (no malformed XML failures)
- supports extracting any parameter name, not just `path`
- preserves legacy precedence (`params.X` > args-derived values)
- matches the old behavior of taking the first matching tag

All tools using <args> have been updated to use the new helper for
path/content/line/regex/file_pattern queries, improving consistency.

Additional changes:
- removed deprecated `parsePathFromArgsParam` from xml.ts
- added complete test suite for `parseParamsFromArgs`, covering:
  - multiple <file> entries
  - root-level tags
  - missing values
  - complex parameter names
  - empty/undefined args

This refactor makes the tooling more resilient to real-world input
(diff blocks, code snippets, and non-well-formed markup) while expanding
support for additional parameters going forward.
@dltechy
Copy link
Contributor Author

dltechy commented Nov 29, 2025

I updated the implementation to be able to parse any parameter, not just path.

export function parseParamsFromArgs(
	args: string | undefined,
	paramNames: string[],
): Record<string, string | undefined> {

Usage

const args = parseParamsFromArgs(params.args, ["path", "diff"])
const relPath = params.path || args.path || ""
const diff = params.diff || args.diff || ""

But to make it work, I had to use regular string parsing to find the relevant tags instead of XML parsing.
Using a proper XML parser fails due to some params, like diff, that have symbols that XML is not happy with (e.g. <<<, >>>)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants