DeepSeek Harness: invalid JSON, bash timeout, snapshot loss

TroubleshootingPublished 2026-10-17Author: DeepSeek Plugin Market
DeepSeek HarnessMALFORMED_RESPONSEtool input is invalid JSONDSMLbash timeouthistory expansionexact integers
DeepSeek Harness faults: malformed JSON (MALFORMED_RESPONSE, no retry), a heredoc '!' burns the 300s bash timeout, and snapshots that downgrade exact integers.

DeepSeek Harness (DSH) has a class of failures that look like "the tool is broken" but really mean arguments got reshaped along the transport chain: the model joins tool arguments into invalid JSON, the adapter fails a one-shot parse at stream end and throws MALFORMED_RESPONSE, hard-aborting the turn with no retry; deepseek-flash mixes model-side DSML call markers into the argument JSON, so the string can never close and the session becomes unusable; a heredoc's exclamation mark in the bash tool triggers interactive history expansion, so the command never runs yet burns the whole 300s timeout; and lossless JSON snapshots downgrade exact integers into objects—validation lets them through, then the transform stage silently loses fidelity. What these four share is this: the error points at "the result is wrong", but what actually broke is "the input was changed in between", so when investigating you walk the chain backwards instead of editing the command or the result (#9402, #9848, #9240, #8810).

DSH plugin tool input is invalid JSON: arguments get joined badly, and there is no retry

One-line conclusion: the adapter parses each tool call's argument JSON once at stream end, and on failure throws MALFORMED_RESPONSE; that code is not in the default retryable set, so the whole turn ends immediately with neither a retry nor the raw text. The error text is DeepSeek Messages stream: tool input is invalid JSON (#9402).

DSH plugin diagnosis: two origins, one error

OriginSignatureNotes
The model intermittently joins arguments badlyThe error is intermittent and may clear on another turn; the first half of the argument looks like JSONParsing runs as a one-shot in the message-stop branch, and failure ends the turn (#9402)
DSML markers mixed inThe error reproduces reliably, recurring on the same model; the session becomes unusableThe model collapses the second half of the argument into DSML markers, so the accumulated string can never close (#9848)

The DSML case needs a special note: this is model-side format leakage—neither DSH's system prompt nor its tool definitions contain any DSML concept (zero hits across the repo), so don't go looking for the cause in your config or plugins (#9848).

DSH plugin four-step handling

  1. Confirm the diagnosis: the error shows tool input is invalid JSON and code=MALFORMED_RESPONSE (#9402).
  2. Emergency fix: run /compact once. In the discussion, after compaction the session recovered (the agent must be idle); if compaction itself fails on an over-long summary, raise the output limit for the summary call or switch to a larger-window model first (#9848).
  3. Config-level mitigation: add the code to the retry allowlist. Note retryableCodes has replace-all semantics, so when you write it you must include all five defaults (#9402):
yaml
- patch:
    id: <your provider adapter id>
    config:
      retryPolicy:
        retryableCodes:
          - EMPTY_RESPONSE
          - RATE_LIMIT
          - SERVER
          - TIMEOUT
          - TRANSPORT
          - MALFORMED_RESPONSE   # the code being added here
  1. A narrower plugin gate: the discussion mentions the community plugin @argszero/cordis-plugin-empty-response-retry, which reclassifies this kind of failure as retryable, a more restrained move than opening up the whole allowlist (#9402).
  2. Remember "shadowing ≠ deleting": /compact only stops later requests from carrying that bad argument; the same model will still reproduce the same kind of output (#9848).

DSH plugin bash tool 300s timeout: the command never ran—a ! triggered history expansion

One-line conclusion: the multi-line command is encoded into eval form and handed to an interactive bash, and the interactive shell's history expansion happens before parsing and does not honor ANSI-C quotes—so the first ! in the script gets the whole line dropped, and the tool waits for a completion marker that never appears, finally burning the timeout and resetting the shell. The symptom is "the model sees only a timeout, never the real error", so it retries repeatedly (#9240).

DSH plugin reproduction diagnosis and a one-line fix

  1. Reproduce: on macOS's default bash 3.2.57, run a heredoc script with a shebang, for example one starting #!/usr/bin/env python3—the ! hits history expansion (#9240).
  2. Key detail: triggering needs the surrounding context before the ! to line up (the discussion gives a cross-check matrix); so "sometimes it runs, sometimes it times out" is not a contradiction (#9240).
  3. One-line fix (verified): turn off both echo and history expansion at initialization:
bash
stty -echo; set +H

set +H turns off history expansion and is the core of this fix (#9240).

  1. User-side workaround (when you cannot change the core): keep ! out of a bare heredoc (for example, write the shebang without an exclamation mark, or escape/quote it in the script), or install the community plugin @argszero/dsh-histexpand-guard first to block such commands (#9240).
  2. Verify: rerun the same script with !; expect the real error (or success) within a few seconds instead of waiting the full 300s (#9240).

DSH plugin snapshots turn exact integers into objects: downgraded only after validation passes

One-line conclusion: lossless JSON validation accepts the true raw JSON value, but the snapshot helper copies it into a plain object with like-named properties, losing its special serialization behavior—so after validation passes, in the transform stage, the downgrade happens and an integer can become an object. (#8810)

DSH plugin three-step confirmation and handling

  1. Confirm the diagnosis: the same value behaves differently in two positions—reported as "invalid output" when declared as an exact integer, but silently turning into a struct as an object property. This inconsistency is this entry's fingerprint (#8810).
  2. Workaround: declare exact-integer fields as normalized decimal strings and encode them back to strings before the snapshot; the matching community plugin in the discussion (dsh-exact-integers) takes this approach (#8810).
  3. Verify: rerun the same tool call and confirm the integer fields in the output are numbers or normalized strings, not objects with properties (#8810).
  4. The position worth writing into feedback: either preserve fidelity, or reject at validation—the only unacceptable thing is "downgrading in the transform stage after validation lets it through" (#8810).

DSH plugin troubleshooting notes

The one piece of investigation wisdom for these four is: the error points at "the result", the cause is in "the input being changed"—follow the chain toward the earlier stages. Eight points:

  1. First split "intermittent" from "reliably reproducible": intermittent leans toward unstable model output, while reliable reproduction prefers a format leak like DSML (#9402, #9848).
  2. MALFORMED_RESPONSE is a "not allowed to retry" code; seeing it end the turn at once is expected behavior (#9402).
  3. /compact is the family's generic emergency fix, but understand that it only shadows (#9848).
  4. Write the retry allowlist in full: under replace-all semantics, a missing entry equals turning off the default retry (#9402).
  5. "The command did not run but timed out" points at shell semantics first, not at tuning the timeout value (#9240).
  6. set +H is the key action for this one; remembering it is more practical than remembering the whole cause (#9240).
  7. For numeric-type distortion, don't look only at validation: passing validation does not mean staying faithful after the transform (#8810).
  8. State the fix status honestly: all four are unfixed in the versions the discussions refer to (0.2.0-rc.2~0.2.1-alpha.*); set +H is a verified one-line fix but is a core-side change, while the user-side means for the other three are config (the retry allowlist), a command (/compact), and plugins (retry / history-expansion / exact-integer guards).

When investigating this kind of "argument distortion" problem, you often have to rule out the plugin layer first—retry policy, history-expansion guards, and exact-integer guards are all plugin-shaped. If you would rather see the environment clearly first, instead of typing commands everywhere, use a visual plugin marketplace such as DSH Plugin Hub: the installed list, install/uninstall history, and system logs are all in one panel.

System Logs

Source: Discussion #9402, Discussion #9848, Discussion #9240, Discussion #8810.

FAQ

In DeepSeek Harness, after `tool input is invalid JSON` (MALFORMED_RESPONSE) the turn just ends—why is there no automatic retry?

In DeepSeek Harness the turn ends with no retry because MALFORMED_RESPONSE is not in the default retryable set. In the message-stop branch when the stream ends, the adapter parses each tool call's argument JSON once; on failure it throws MALFORMED_RESPONSE, while the retry loop only handles the other five error classes, so the whole turn ends at once. To mitigate, add that code to the retry allowlist in your profile (note it replaces the whole list), or use a community plugin that reclassifies this failure as retryable.

In DeepSeek Harness a session reports `tool input is invalid JSON` and is then unusable—what is the emergency fix?

In DeepSeek Harness the emergency fix is to run /compact once (the agent must be idle). In the discussion, after compaction the session recovered, because compaction rewrites the context so later requests no longer carry that bad argument; if compaction itself fails on an over-long summary, first raise the output limit for the summary call or switch to a model with a larger window. Note this is mitigation, not a cure—the same model will still reproduce the same kind of output.

In the DeepSeek Harness bash tool I write a heredoc script with a shebang, the command clearly did not run, yet it waits three hundred seconds and times out—why?

In the DeepSeek Harness bash tool this timeout happens because the exclamation mark in the script triggers the interactive shell's history expansion. The multi-line command is encoded and run in eval form; history expansion happens before parsing and does not honor ANSI-C quotes, so the whole line is dropped, and the tool waits for a completion marker that never appears, finally burning the whole timeout. The one-line fix is to turn history expansion off at initialization (while keeping echo off); on the user side you can avoid it for now by keeping ! out of a bare heredoc or using a form that does not trigger expansion.

In DeepSeek Harness, why do exact integers in tool results show up in the output as objects with properties?

In DeepSeek Harness the exact integer becomes an object because the snapshot helper copies the raw JSON value into a plain object, losing its special serialization behavior. Validation accepts such a value, but the downgrade happens in the later transform stage, so the same integer is reported as invalid when declared as an exact integer and silently turns into a struct as an object property. To avoid it, declare these integer fields as normalized decimal strings, or use the matching community plugin to encode them back to strings before the snapshot.

In DeepSeek Harness, what is a DSML marker, and why does it end up mixed into tool arguments?

DSML is a class of model-side tool-call marker syntax; it is not a DeepSeek Harness concept. When the model emits the first half of the argument as JSON but collapses the second half into these markers, the accumulated string can never close into valid JSON, so parsing fails at a fixed position and throws MALFORMED_RESPONSE. This is model-side format leakage: the host's system prompt and tool definitions contain no such markers, and the workaround is to compact the context or switch models.

Related Terms

MALFORMED_RESPONSE
MALFORMED_RESPONSE is the error code DeepSeek Harness uses when response content does not match the expected structure, for example when tool arguments cannot be parsed into JSON. It is not in the default retryable set, so it usually ends the current turn immediately.— https://github.com/deepseek-ai/deepseek-harness/discussions/9402
DSML
DSML is a class of model-side tool-call marker syntax, shaped like parameter tags with special delimiters. It is not part of the DeepSeek Harness protocol, and when it appears inside tool arguments it keeps the argument JSON from ever closing, which triggers the parse failure.— https://github.com/deepseek-ai/deepseek-harness/discussions/9848
heredoc and history expansion
A heredoc is shell syntax for inlining multi-line text; history expansion is the interactive shell's feature of replacing a segment starting with an exclamation mark with a past command. When the two collide, the exclamation mark in the script makes history expansion swallow the whole line, so the command never runs.— https://github.com/deepseek-ai/deepseek-harness/discussions/9240
lossless JSON snapshot
A lossless JSON snapshot is DeepSeek Harness's mechanism for preserving raw numeric semantics when materializing a tool result into the session, used to avoid losing precision on large integers. The current implementation loses a value's special serialization behavior when it copies the raw JSON value, so an exact integer is downgraded into a plain object during the transform stage.— https://github.com/deepseek-ai/deepseek-harness/discussions/8810

Sources