DeepSeek Harness MALFORMED_RESPONSE: refusal stop reason
A 24-character Chinese operations instruction — "today's daily K-line data is updated, you can run the scheduled task early" — streamed reasoning normally, with the model even restating the task, and then the stream ended with stop_reason: refusal while the UI reported "this turn failed / MALFORMED_RESPONSE". That error code is easy to read as "the response was truncated" or "the model rejected you", but semantically it says exactly one thing: the client does not recognize this stop reason (#11337).
DeepSeek Harness: Layer 1: MALFORMED_RESPONSE means "I do not recognize this"
It is the client's classification of the response stream, not a transport error and not a moderation verdict.
- Read the full text:
DeepSeek Messages stream: unsupported stop reason refusal, with codeMALFORMED_RESPONSE. - Read the stream contents: first a reasoning block where the model correctly restates the task and plans which scheduled item to run.
- Then a finish block whose
reason.kindis error and whosefailure.messageis the sentence above. - In other words: content production succeeded, and the failure happened in the closing stage.
- So "malformed" here means "I have no handler for this end reason", not "the payload is broken".
DSH plugin: Layer 2: stopReason() knows only four values
The adapter handles end_turn, stop_sequence, tool_use, and max_tokens only; everything else goes to malformed(), and refusal lands in "everything else".
- Follow the arrival path:
message_deltahandsstop_reasontostopReason(). - Read the branches: the four known values each map somewhere, and all others go to
malformed(). - The community ran that function in an isolated environment: input
refusalproduced exactly the error you see. - Conclusion: the client behavior is predictable and deterministic, no guessing required.
- This is also the only part of the article that yields a definite conclusion.
DeepSeek Harness: Layer 3: whose semantics is refusal anyway
It is a stop reason from upstream; the client classifies it as an error but cannot explain why upstream sent it.
- Anthropic's documentation lists
refusalas a legal Messages stop reason, but that document describes Claude. - It does not establish DeepSeek's contract, nor prove whether this particular refusal was reasonable.
- The reporter's input contains no violence, self-harm, illegal, sexual, personal-data, or political content; it is a scheduling instruction.
- The reporter's hypothesis is that a post-hoc safety classification read "run the scheduled task early" as an external action — a hypothesis, not a conclusion.
- Stop here: the only half that belongs in documentation is the client mapping.
DSH Plugin: The boundary between certain and uncertain
Keeping the two kinds of conclusion separate prevents describing a client defect as a model problem and prevents judging on the provider's behalf.
| Item | Certain? | Basis |
|---|---|---|
| The stream ended cleanly and reasoning was produced | Yes | event sequence visible |
| The client maps only four stop reasons | Yes | source code and isolated run |
refusal falls into the malformed branch | Yes | same as above |
| Why the provider returned refusal | No | no official explanation |
| Whether it was a safety misclassification | No | reporter's hypothesis |
DeepSeek Harness: How to handle this class of error
What the client side should do is "preserve the upstream reason and map it to a distinct state", not flatten every unknown value into one error code.
- Keep the original upstream
stop_reasonvalue in the normalized result; do not drop it. - If
refusalis a legal value for that provider, map it to a distinct "model declined" state instead ofMALFORMED_RESPONSE. - Give the user a readable explanation without exposing internal reasoning.
- Do not retry the same rejected request indefinitely.
- Add a regression test: a stream with a valid reasoning block followed by
stop_reason: "refusal". - Investigating provider behavior is a separate task; the two can run in parallel and should not block each other.
DSH plugin: What to collect when reproducing
Enough information is enough; do not bring credentials or business data into it.
- A redacted
message_deltaevent, includingstop_detailsif present. - The client version and the provider version.
- The result of a second run with the same input, to judge whether it reproduces reliably.
- When the event happened and whether it was retried.
- Explicitly exclude credentials, private prompts, and session identifiers.
A reusable judgment framework
When a report says "an unknown value was treated as an error", ask three questions first: who produced the value, how does the client map it, and what do the docs promise.
- Who produced it: an upstream response field or a client inference. Here it is upstream's
stop_reason. - How the client handles it: is there an explicit branch, and where do unknown values land. Here they land in
malformed(). - What the docs promise: does that provider publicly list the value. Here only Claude's docs mention it.
- If all three still leave "why did upstream send it" unanswered, do not overreach when drawing conclusions.
- The framework also applies to other
unsupported ...errors: most indicate a mapping gap, not corrupted data.
Cautions
Keep the two halves of the story separate in every report.
- Do not treat MALFORMED_RESPONSE as a network problem. It appears at stream teardown, not in transport.
- Do not infer a content violation from it. The client has no authority to interpret.
- Do not retry the same message repeatedly. First confirm whether it reproduces reliably.
- Do not treat Anthropic's docs as DeepSeek's contract. The same field name may mean different things across providers.
- Separate the two halves in a report. "Client mapping gap" and "provider refusal reason" must be written separately, or maintainers cannot locate the problem.
If your message is not unsupported stop reason, it belongs to another teardown problem — check the full structure of the finish block.
If it really is unsupported stop reason but the value is not refusal, the logic is identical: map the gap first, then discuss upstream behavior.See DeepSeek Harness thinking-only output: empty stop succeeds for the related case.
FAQ
No, the response was not truncated: the reasoning block streamed normally and the stream ended cleanly, and DeepSeek Harness recognizes only end_turn, stop_sequence, tool_use, and max_tokens, so every other value goes through malformed() and refusal is reported as a parse failure.
No, this error does not mean the model judged your request out of bounds: a client mapping error in DeepSeek Harness only proves it does not know the value; it cannot prove why the provider emitted it. The community stated plainly that refusal is a stop reason from upstream, and the client has no authority to interpret it.
That document describes Claude's behavior and does not establish DeepSeek's contract, which is why DeepSeek Harness does not accept refusal. DSH's DeepSeek Messages adapter currently maps only four values, with refusal not among them, which is a client-side mapping gap.
Do not auto-retry first in DeepSeek Harness: compare a second run with the same input to see whether it reproduces, then decide if it is intermittent or stable. Even if stable, refusal should map to a distinct rejection state rather than MALFORMED_RESPONSE, and infinite retries are worse.
When reporting this to DeepSeek Harness, collect a redacted message_delta event (including stop_details if present) and the client and provider versions. Do not include credentials, private prompts, or session identifiers.
Related Terms
- MALFORMED_RESPONSE
- MALFORMED_RESPONSE is the error DeepSeek Harness returns when a response stream cannot be parsed as expected. It means the client did not recognize some response shape, not that the transport failed or the content was truncated.— https://github.com/deepseek-ai/deepseek-harness/discussions/11337
- stop_reason
- stop_reason is the field that identifies why a streamed response ended, with values such as end_turn, stop_sequence, tool_use, and max_tokens. The client uses it to decide how to finish, and unknown values are usually classified as errors.— https://github.com/deepseek-ai/deepseek-harness/discussions/11337
- refusal
- refusal is a stop reason indicating the model declined to complete a request. Anthropic documents it as a legal Messages value, but whether the contract matches across providers has to be confirmed separately.— https://github.com/deepseek-ai/deepseek-harness/discussions/11337
- malformed()
- malformed() is the function in the DeepSeek Messages adapter that turns an unknown stop reason into an error. Currently every value other than the four known ones falls into this branch.— https://github.com/deepseek-ai/deepseek-harness/discussions/11337
Sources
- #11337 — Benign Chinese ops prompt → stop reason refusal → client reports MALFORMED_RESPONSE· deepseek-ai (GitHub Discussions)
- deepseek-ai/deepseek-harness (source repository)· GitHub