Problem
A raw newline byte inside a quoted string in the function-call DSL fails with the serde-level message:
MCP -32602: control character ( -) found while parsing a string
The error is technically correct and the grammar is fine (ADR-016 string escapes follow JSON and already ship), but the message teaches nothing. Worse, the natural fix a caller tries — writing \n in the JSON tool argument — still fails, because the MCP transport decodes that to a literal newline byte before the DSL parser runs. The working form from an MCP client is the double escape \\n. Nobody discovers this unaided; users have repeatedly landed on the wrong "must switch to the JSON op form" workaround instead.
Fix
When string decoding fails on a control character, return an error that:
- names the offending character and its position,
- states that string escapes follow JSON (
\n, \t, \", \\),
- notes that callers passing
ops through a JSON transport (every MCP client) must double-escape (\\n in the wire form).
Grammar unchanged — this is error-message-only. Normative basis: ADR-084 §3c (PR #490). Parser tolerance for raw control chars was considered and rejected there (Alternatives §6).
Where
crates/khive-request — parse_value hands the quoted slice to serde_json::from_str; wrap that error.
Problem
A raw newline byte inside a quoted string in the function-call DSL fails with the serde-level message:
The error is technically correct and the grammar is fine (ADR-016 string escapes follow JSON and already ship), but the message teaches nothing. Worse, the natural fix a caller tries — writing
\nin the JSON tool argument — still fails, because the MCP transport decodes that to a literal newline byte before the DSL parser runs. The working form from an MCP client is the double escape\\n. Nobody discovers this unaided; users have repeatedly landed on the wrong "must switch to the JSON op form" workaround instead.Fix
When string decoding fails on a control character, return an error that:
\n,\t,\",\\),opsthrough a JSON transport (every MCP client) must double-escape (\\nin the wire form).Grammar unchanged — this is error-message-only. Normative basis: ADR-084 §3c (PR #490). Parser tolerance for raw control chars was considered and rejected there (Alternatives §6).
Where
crates/khive-request—parse_valuehands the quoted slice toserde_json::from_str; wrap that error.