DeepSeek Harness web_search abort and web_fetch pipe loss
**DeepSeek Harness (DSH)'s web_search and web_fetch have two defects that are easily misjudged as "network jitter", and what they share is that the result is already wrong on the write side: the search one is that one failed sub-query voids the whole batch—the fan-out uses a shared cancel signal, so any failed query cancels the others in the same batch, and the later collection logic still throws the first error, so results that "already succeeded and were already paid for on a per-call service" are discarded along with it; the fetch one is that consecutive pipes in a table cell get collapsed into one—Markdown tables require pipes to be escaped character by character, but the implementation uses "replace a run of consecutive pipes as a whole", so the semantics of code expressions are quietly changed and it cannot be recovered from the Markdown result side (three different numbers of pipes render to the same shape) (#8794, #9630).
DSH plugin one failed query voids the whole batch: the fan-out is dragged down by a shared cancel signal
One-line conclusion: parallel sub-queries share one cancel signal, so any failure aborts the rest; even though the collection uses an "await all" form, it still throws the first error afterward, so the result-merge step never runs—the tool returns only one error and the successful results are all lost. The symptom is "a multi-query search reporting only one error and no results at all" (#8794).
DSH plugin diagnosis: two checks, one on shape and one on the bill
- Look at the return shape: one call carrying several sub-queries returns only one error and no result entries—that is this entry; if it returns partial results and labels one sub-query as failed, that is a different (partial-success) shape (#8794).
- Look at the billing record (very telling): on a per-call search service, each sub-query is an independent billed round. If your backend shows a charge count equal to the number of sub-queries you submitted while the tool returns only an error, the results were discarded—you paid but got nothing (#8794).
DSH plugin three-step handling and fix direction
- Reduce the number of sub-queries (temporary workaround): send only one query at a time, turning "batch search" into several single queries—trading concurrency for availability (#8794).
- Fix (given in the discussion, three changes together): remove the shared abort; return the successful queries' results one by one and label the failed one by name in the result; fail as a whole only when all fail (#8794).
- Verify: build a case where "one query is bound to fail and the other two are bound to succeed" and expect the return to show two successful results plus one failure label, rather than a single whole error (#8794).
- Note what it means for cost: this is not just an experience problem—on a per-call service, a whole-batch void means money wasted, so the fix priority should be higher than for an ordinary UI defect (#8794).
DSH plugin table pipes get collapsed: Markdown escaping written as "replace a run"
One-line conclusion: when rendering a cell, a "replace a run of consecutive pipes as a whole" regex squashes || into |, while GFM requires pipes to be escaped character by character—so the code expression first||last is written as first|last and the meaning changes; worse, this damage cannot be recovered from the Markdown result side (|, ||, ||| all render to the same shape). The symptom is a successful fetch with no truncation, but content quietly rewritten (#9630).
DSH plugin three-step confirmation and handling
- Confirm the diagnosis: fetch a page with a code table (a
||-style expression in a cell) and check whether the pipes in the converted Markdown decreased; at the same time confirm the request succeeded and the result was not truncated—"successful but rewritten" is this entry's fingerprint (#9630). - Temporary workaround one: fetch the raw content rather than the rendered table (for example a source page or an API return), bypassing this conversion path (#9630).
- Temporary workaround two: don't let the model judge code based on that table, and double-check against the original page when needed (#9630).
- Fix: change "replace a run" to per-character escaping—the reporter provides a minimal patch that can be extracted on its own (#9630).
- Verify: refetch the same page and confirm the number of pipes in the Markdown matches the original page (
||is still\|\|, two characters rather than one) (#9630).
DSH plugin troubleshooting notes
The key point for both is "first tell apart a failure of the search/fetch itself from a result that got changed in the conversion step". Seven points:
- For the search entry, check shape + check the bill; using both together is most accurate (#8794).
- "Only one error, zero results" ≠ "really found nothing": in a multi-sub-query scenario, suspect a whole-batch void first (#8794).
- The correct semantics of fan-out is "each sub-query succeeds or fails independently", not "all succeed or all fail" (#8794).
- Write the cost impact into your conclusion: a whole-batch void on a per-call service is real money (#8794).
- For the fetch entry, "successful but rewritten" is more dangerous than an error: it does not put you on your guard (#9630).
- The damage is irreversible: don't expect to fix the pipes at a downstream parse stage—the information is lost at conversion time (#9630).
- State the fix status honestly: both are unfixed in the versions the discussions refer to (around
0.2.1-alpha.2); the search entry's fix (drop the shared abort + partial-success semantics) and the fetch entry's patch are both unmerged, so for now only user-side workarounds like "split into single queries" and "fetch raw content" exist.
When investigating search and fetch problems, it is easy to be led astray by the "network" direction. If you want to confirm the "environment" layer first—for example whether a given search/fetch plugin was ever installed and how many versions—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.

Source: Discussion #8794, Discussion #9630.
FAQ
In DeepSeek Harness the whole batch is voided because the fan-out implementation uses a shared cancel signal: any failed query aborts the others in the same batch, and even though the collection logic uses an 'await all' form, it still throws the first error afterward, so the result-merge step never runs. The effect is that the tool returns only one error while results that actually succeeded (and were paid for on a per-call service) are discarded. The fix direction is to drop the shared abort, return the successful queries one by one and label the failed one by name, and fail as a whole only when all fail.
In DeepSeek Harness the way to tell is to look at the return shape: if the tool returns only one error and no result entries, while your query really did contain several sub-queries, it is more likely a whole-batch void; if it returned results but labeled one sub-query as failed, that is partial success. Another supporting signal is cost—a per-call search provider records each sub-query, so if the backend shows a charge count equal to the number of sub-queries you submitted while the tool returned only an error, the results were discarded.
In DeepSeek Harness the double pipe becomes single because the renderer replaces a run of consecutive pipes in the cell with a single escaped pipe. The Markdown table convention requires pipes to be escaped character by character, while the current implementation uses a 'replace a run of consecutive pipes together' form, so a double pipe is squashed into one. This changes the semantics of code expressions, and it cannot be recovered from the Markdown result side—three different numbers of pipes render to the same shape, so the information is already lost at conversion time.
In DeepSeek Harness there are two workarounds: first, change the fetch target itself (for example, fetch the raw source or an API response instead of the rendered table); second, after fetching, do not rely on the Markdown table to judge code, and double-check against the original page when needed. A real fix has to be in the renderer, because the damage happens on the write side and no later parsing can recover it.
In DeepSeek Harness the search one does—on a per-call search service each sub-query is an independent billed round, so a whole-batch void means you paid but got no results. The fetch one does not affect billing, but it affects judgment quality: a code expression's OR operator shown as a single pipe may lead the model to a wrong conclusion.
Related Terms
- fan-out
- Fan-out is an execution style that splits one tool call into several parallel sub-requests, in the search scenario appearing as one web_search carrying several query terms. The fan-out semantics expect 'each sub-query succeeds or fails independently', but if the cancel signal is shared, one failure drags down all of them.— https://github.com/deepseek-ai/deepseek-harness/discussions/8794
- allSettled semantics
- allSettled semantics means waiting for all sub-tasks to finish and collecting results regardless of success or failure, rather than aborting at the first failure. Search fan-out should adopt this semantics so that partial success can still return.— https://github.com/deepseek-ai/deepseek-harness/discussions/8794
- pipe escaping in GFM tables
- A GFM table uses pipes to separate cells, so a pipe inside cell content must be escaped as backslash plus pipe. The escaping must be handled character by character: two consecutive pipes are 'two characters', not 'a run'.— https://github.com/deepseek-ai/deepseek-harness/discussions/9630
- web_fetch
- web_fetch is the tool DeepSeek Harness uses to fetch a web page and convert it to text, usually Markdown. HTML tables are rendered as GFM tables, so the correctness of table-content escaping directly determines whether the fetched result faithfully reproduces the page.— https://github.com/deepseek-ai/deepseek-harness/discussions/9630
Sources
- #8794 — web_search: one failed query aborts the other queries and discards their (billed) results· deepseek-ai (GitHub Discussions)
- #9630 — web_fetch collapses consecutive pipes in HTML table cells· deepseek-ai (GitHub Discussions)