You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Bug] MALFORMED_RESPONSE: "tool input is invalid JSON" on large tool-call arguments
#11843
本轮运行失败 DeepSeek Messages stream: tool input is invalid JSON MALFORMED_RESPONSE
and the whole turn is discarded, with no automatic retry.
Environment
DSH Desktop (Windows 11), provider deepseek
Package: @deepseek-ai/dsh-llm-deepseek (bundled in the desktop install)
Model route: whatever the desktop profile is configured with; happens on ordinary chat turns, not exotic tooling
Root cause (from the installed bundle)
In dsh-llm-deepseek/lib/index.js, the tool-call block is validated once:
letparsed;try{parsed=JSON.parse(content.arguments);}catch(_invalidProviderToolJson){returnmalformed("tool input is invalid JSON");}
So if the streamed arguments string arrives truncated or otherwise corrupted, the adapter aborts the turn. Note the neighbouring guard is if (reason.kind !== "max-tokens"), i.e. a max_tokens cut is deliberately tolerated — these failures are not max-tokens, they look like stream corruption.
There is also a second, related throw in parseSse:
In a single long session this happened twice, both times on a tool call with a large argument payload (several KB of text, a lot of CJK characters and escaped quotes/newlines inside a single edit/write argument). Tool calls with small arguments never failed in the same session, on the same model route.
Impact
For interactive use it is mostly annoying (re-send the request). For unattended runs (scheduled prompts, long tool chains) it silently kills the step, and the partial work is lost from the conversation even though the side effects already happened on disk.
Suggestions
Tolerate / repair a malformed arguments string instead of failing the turn — e.g. attempt a closing-bracket repair, or surface the raw string as the tool input and let the tool validate it.
Retry by default on MALFORMED_RESPONSE. The plumbing already exists: dsh-agent-loop awaits dispatch.waterfall("agent/request-error", …) and continues when the returned action is { kind: "retry" }. A built-in retry policy for transport-level parse failures (1–2 attempts, no user-visible failure on the first) would make this invisible.
Optionally, keep the failed attempt's raw arguments in the log so it can be reported without reproducing.
Workaround we currently use
Keep every single tool-call argument small (write long files in several small appends, avoid multi-KB inline strings). Effective, but it is a workaround for a client-side robustness issue rather than a fix.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Summary
A turn fails with
MALFORMED_RESPONSE:and the whole turn is discarded, with no automatic retry.
Environment
deepseek@deepseek-ai/dsh-llm-deepseek(bundled in the desktop install)Root cause (from the installed bundle)
In
dsh-llm-deepseek/lib/index.js, the tool-call block is validated once:So if the streamed
argumentsstring arrives truncated or otherwise corrupted, the adapter aborts the turn. Note the neighbouring guard isif (reason.kind !== "max-tokens"), i.e. amax_tokenscut is deliberately tolerated — these failures are not max-tokens, they look like stream corruption.There is also a second, related throw in
parseSse:Reproduction pattern (anecdotal but consistent)
In a single long session this happened twice, both times on a tool call with a large argument payload (several KB of text, a lot of CJK characters and escaped quotes/newlines inside a single
edit/writeargument). Tool calls with small arguments never failed in the same session, on the same model route.Impact
For interactive use it is mostly annoying (re-send the request). For unattended runs (scheduled prompts, long tool chains) it silently kills the step, and the partial work is lost from the conversation even though the side effects already happened on disk.
Suggestions
argumentsstring instead of failing the turn — e.g. attempt a closing-bracket repair, or surface the raw string as the tool input and let the tool validate it.MALFORMED_RESPONSE. The plumbing already exists:dsh-agent-loopawaitsdispatch.waterfall("agent/request-error", …)and continues when the returned action is{ kind: "retry" }. A built-in retry policy for transport-level parse failures (1–2 attempts, no user-visible failure on the first) would make this invisible.argumentsin the log so it can be reported without reproducing.Workaround we currently use
Keep every single tool-call argument small (write long files in several small appends, avoid multi-KB inline strings). Effective, but it is a workaround for a client-side robustness issue rather than a fix.
All reactions