[Engine] An array or object tool parameter with a raw newline inside a string reaches the client as a string
Maintainers usually reply within 3 days
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 78/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- python
- Domain
- backend-api-design
Research direction
Read the two parsing paths named in the report: parse_tool_call at serve/frontend.py:931-935 and the streaming parser's raw state at serve/frontend.py:1274-1277. Reproduce with a non-string parameter containing a raw newline inside a JSON string, then check both paths handle it consistently. Done when the value reaches the client as an array or object and malformed JSON still uses the existing fallback.
Written by the indexing model from the issue text.
Description
Area
[Engine] (speed, kernels, models, the server and API)
Desktop app, Terminal or source?
Desktop app (Windows, Linux or Mac)
What happened
A tool call whose array or object parameter holds multi-line text reaches the client as a string instead of the array or object, and the client rejects the call.
In the Qwen XML form (<parameter=edits>…</parameter>) the model writes the value as raw text. For a parameter whose declared type is not string, the parser runs json.loads(value) and, when that raises, silently passes the raw text through as a string:
parse_tool_call,serve/frontend.py:931-935on main46c152a1- the streaming parser's
rawstate,serve/frontend.py:1274-1277
The model typically writes a line break inside a JSON string as a real newline, not as \n. That is natural in this format and is what an agent editing a Markdown file or source code does. Python's default json.loads (strict=True) refuses a raw control character inside a string, so the whole value falls back to a string:
Invalid control character at: line 1 column 74 (char 73)
The value itself was a correct array of {"old_str", "new_str"} objects. json.loads(value, strict=False) parses it into exactly that array.
Seen with Forge (VS Code agent) as the client, on an edit_file call whose edits parameter is declared as an array. The client answered edits arrived as a string, not an array and is not valid JSON. The model recovered by switching to a flat single-edit form, but it costs a round each time, and it happens often on long agent sessions that edit Markdown.
Expected: a raw newline or tab inside a string in a non-string parameter parses as part of that string.
Suggested fix: json.loads(value, strict=False) at both sites. Valid JSON parses exactly as before. The only change is that raw control characters inside strings are accepted, which is what the XML parameter format produces. A parameter that is still not JSON keeps today's fallback.
Smallest steps or command that reproduce it
import json
s = '[{"old_str": "a", "new_str": "line one\nline two"}]' # a real newline inside new_str
json.loads(s) # ValueError: Invalid control character at: line 1 column 39 (char 38)
json.loads(s, strict=False) # [{'old_str': 'a', 'new_str': 'line one\nline two'}]
Feeding parse_tool_call a <tool_call><function=edit_file><parameter=edits> block with that value and a schema declaring edits as array returns arguments["edits"] as str.
Reproduction status
Reproduced locally
Strata version
engine 0.1.52 (the code paths above checked on main 46c152a1)
Graphics card, memory and system
2x RTX 5060 Ti 16 GB + RTX 3060 12 GB, Windows 10 Pro
Model, size and settings
Qwen3.8-Flash-Next IQ2_XS, 400K context. The model is not the cause: the parameter value it wrote was correct JSON apart from the raw newlines.
- Dominant language
- C++
- Stars
- 11.6k
- Forks
- 1k
- PR merge metrics
- No merged PRs in 30d
Getting set up
This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from Niko1221/Strata
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
Maintainers usually reply within 3 days
-
[Engine] HIP source build fails since v0.1.45: `__shared__ alignas(16) int4` in iq_kernels.cu (expdec verify window)Possibly taken A pull request linked to this issue is open or already merged. Open
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
Niko1221/Strata#4589 · 1 comment ·
Maintainers usually reply within 3 days
-
[Engine] strata-sycl.sh drops every STRATA_* variable whose value is 0, so the documented STRATA_PREFILL_MMQ=0 (FP16 prompt path) never reaches the engine; "off" works by accidentPossibly taken @ctr-137 claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
Maintainers usually reply within 3 days
-
[Other] tools/ab_engine.py reuses ab_<arm>_r<n>.log in the temp dir across runs, so a later A/B appends its engine logs to an earlier onePossibly taken @ctr-137 claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 3 days
-
[Other] setup.sh --update on an Intel (SYCL) install always ends with "the engine was NOT: it is still 0.1.12": engine_version() reads the launcher script the config names as exePossibly taken @ctr-137 claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
Maintainers usually reply within 3 days
Similar issues
-
good first issue invalid
Difficulty 1/5 Under an hour Newbie friendliness 72/100
DanielJerolm/gpcc#74 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
patrick-hudson/put.gd-desktop#808 ·
Maintainers usually reply within 1 day
-
DPI change is not fully handled in the cascading window on WindowsPossibly taken @yukawa claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
Maintainers usually reply within 4 days
-
Difficulty 2/5 1-3 hours Newbie friendliness 77/100
dasher-project/Dasher-GTK#97 ·
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
Maintainers usually reply within 1 day