fix: escape control characters in LLM tool call arguments JSON#2893
Conversation
|
looks nice - @salman1993 is active in there with goose-llm crate so probably good to get a blessing there. |
2dd1d0e to
97ca274
Compare
salman1993
left a comment
There was a problem hiding this comment.
goose-llm crate is currently not used by goose. can you please describe where / how you ran into this error? #2892
i have a feeling the bug is in goose crate and not goose-llm
|
@salman1993 I ran into this error using the goose cli. I fixed in the |
|
@salman1993 bump 🙏 |
|
Let me bump this to the goose dev team for you! |
97ca274 to
8f36f4e
Compare
|
I removed the changes to |
DOsinga
left a comment
There was a problem hiding this comment.
I think we should move the escaping level one higher - see my remark and then it should be good to go
| // Escape literal control characters in the arguments string to make it valid JSON. | ||
| // This handles cases where the LLM might output raw newlines or other control | ||
| // characters within string values in the JSON arguments. | ||
| let escaped_arguments = json_escape_control_chars_in_string(&arguments_str); |
There was a problem hiding this comment.
so what's happening here is that we receive a json document from the provider that almost certainly is correct json, but that the arguments element in it is doubly encoded json and that second tag is not always entirely correct?
if so I think we should slightly change the approach here - move the entire json parsing into utils and call it safely_parse_json and first try if it parses without your replacements and only if it doesn't do the escape replacements.
arguments could be something like {"key1": "value1",\n"key2": "value"} which contains a \n but is perfectly fine, while you are trying to fix {"key1": "value1\n","key2": "value"} which is not
There was a problem hiding this comment.
@DOsinga updated the PR with your suggestions. PTAL @DOsinga @salman1993 🙏
e450aab to
5fb38da
Compare
|
can you do the DCO thing and we can get this in 🙏 https://github.com/block/goose/pull/2893/checks?check_run_id=46249519944 |
|
oh this is a nice one, kudos |
- Add json_escape_control_chars_in_string() utility function - Apply fix to OpenAI and Databricks response parsers - Enhance error messages with raw and processed arguments - Add comprehensive test coverage for control character escaping Signed-off-by: Julian Brown <contact@julianbrown.dev>
Signed-off-by: Julian Brown <contact@julianbrown.dev>
52b5e31 to
a93c619
Compare
|
@DOsinga done! |
|
thanks! |
|
Hi! I've been tracking this issue and it's nice that most control characters are now properly escaped, but I think a few things were left on the table. The quotation mark JSON is overly strictly defined in this sense. Escaping the quotation mark is only strictly necessary if the first non-white space character is a "meaningful" one, i.e. one of
I additionally find that Qwen-3 will sometimes fail to properly close the JSON, i.e. to only use one
and combining the two:
|
|
good points, @veriditin - but at that point I think that search & replace with regexps is not going to do it and we're going to need a tolerant json parser - https://crates.io/crates/json_partial looks like an option? not sure it does your " in the middle of a string though |
* main: chore: small refactor on agent.rs (#3703) docs: Add GitMCP Tutorial to Extensions Library (#3716) chore: Speed up CI (#3711) Fix tool vector tests (#3709) docs: GitMCP Tutorial (#3708) Remove unused dependencies (#3626) feat: update Groq models for better tool calling support (#3676) chore: remove ffi libraries and related code (#3699) only run google analytics in prod (#3395) Fix typo in quickstart document (#3447) fix: pricing estimation for OpenRouter in goose-cli (#3675) fix: escape control characters in LLM tool call arguments JSON (#2893) feat(githubcopilot): add ability to fetch supported models (#2717) Create a message ID for tool response messages (#3591) fix: Fixed 404 broken link to extensions page in index.md (#3623)
…#2893) Signed-off-by: Julian Brown <contact@julianbrown.dev> Co-authored-by: Julian Brown <jbrown@stripe.com> Signed-off-by: Adam Tarantino <tarantino.adam@hey.com>

Testing
Backwards Compatibility
This change is fully backwards compatible. It only affects the processing of malformed JSON arguments that would have previously failed to parse. Valid JSON arguments continue to work exactly as before.
Related Issues
Fixes #2892