Repository navigation
[Bug] DeepSeek Messages 400s when a session's tool list becomes all-deferred (defer_loading) #10163
Replies: 2 comments
|
Reproduced your diagnosis, and shipped a plugin that repairs the request in front of the dispatch — so a session that is already in this state becomes usable again without a fork of the adapter. The shape, confirmed against the shipped codeYour step list matches
So the invariant for a route in that mode is simply: a wire entry is loadable iff its name was already declared, non-deferred, in The plugin
npm install github:argszero/dsh-all-deferred-tools-guard(Not on npm yet — the registry token on this machine is unavailable, so the git form is the honest one today. Same package name is reserved for when it lands.) It listens on the Two triggers:
The second trigger exists because the update mode is resolved per model inside the adapter and is not readable from the waterfall — so the prediction is an over-approximation and the provider is the backstop. Evidence
Two things it does not claim: it repairs the request, not the history — the session still holds a table where every active tool arrived as an addition, and the placeholder is what keeps the wire list legal; and a model that calls the placeholder reaches the ordinary unknown-tool path, the same trade pi-ai makes. Your proposed upstream fix ( If you still have one of the four affected sessions, mounting it in |
|
One correction to the evidence in my earlier comment, and it changes a support claim rather than the diagnosis. I said the cross-line probe ran on
10/10 — the failure you reported and the repair this plugin performs are identical on every line the plugin claims, so a reader can pick any of them and reproduce your case. That exercise also found the range wrong in one place. The Two smaller things in the same pass, because a probe that cannot be trusted not to abort is not a probe: the script was enumerating every entry under Same install path as before, now at the tip of npm install github:argszero/dsh-all-deferred-tools-guardStill not on npm (registry token unavailable on this machine), and the upstream sentence from my earlier comment stands unchanged: the durable fix belongs in |
Uh oh!
There was an error while loading. Please reload this page.
Summary
When an existing session's tool set changes so that every tool is "new" relative to the session's first request,
@deepseek-ai/dsh-llm-deepseeksends atoolsarray where every entry hasdefer_loading: true. The Messages endpoint rejects it with 400INVALID_REQUEST:The session is then permanently unusable: every following request has the same shape, so retrying never helps. We hit this in 4 sessions on dsh desktop 0.2.1-rc.2 (provider
deepseek-account, modeldeepseek-flash).How the malformed request is produced
request/headerwith onlyrun_code(PTC presentation).ToolHistoryProjectionkeeps that header as the declaration baseline.tool-presentationlayer did not apply on that resume, so the scope fell back to native.buildRequest(agent-loop) appends adeveloper/messagewith 67tool-additionblocks and 1tool-removal(run_code), andprojectToolUpdatesmarks every additiondeferLoading: true.run_codeis gone and the provider receives 68 tools, alldefer_loading: true-> 400.Why it is not handled today
@deepseek-ai/dsh-llm-pi-aialready handles this exact shape foranthropic-messagesroutes: when every tool is deferred, it prependsANTHROPIC_TOOL_UPDATE_PLACEHOLDER(seellm-pi-ai/lib/index.js, thetools.every((tool) => tool.deferLoading === true)branch). The DeepSeek adapter'sserialize()inllm-deepseek/lib/index.jshas no equivalent guard, so the raw all-deferred list goes out unchanged.Proposed fix
In
llm-deepseek's request serializer: ifoptions.toolsis non-empty and every tool hasdeferLoading === true, prepend one non-deferred placeholder tool (name, description, empty object schema), mirroring the pi-ai adapter. A local patch doing exactly that (same byte length, injected placeholder) is what we are testing now.Notes
agent-preset/locked). The tool set changed because the presentation layer resolved differently on resume.toolUpdate(e.g.deepseek-v4-pro, which skips the deferred projection path) or starting a new session.Happy to provide session-log excerpts (request/header + developer/message sequences) if useful.
All reactions