DeepSeek Harness aborts tool calls before dispatch

TroubleshootingPublished 2026-10-20Author: DeepSeek Plugin Market
DeepSeek HarnessDSHauto-reviewABORTED_BEFORE_DISPATCHpermission autoCordis
Switching to /permission auto mid-turn makes every later DeepSeek Harness tool call return ABORTED_BEFORE_DISPATCH while the turn still completes.

Mid-turn you switch to /permission auto, and from the next tool call onward everything returns ABORTED_BEFORE_DISPATCH, while the turn still ends as completed. The error text is only two lines: tool call aborted before dispatch and code: "ABORTED_BEFORE_DISPATCH". This is not the model misbehaving and not a broken tool: DeepSeek Harness (DSH) reconfigures auto-review when the permission preset changes, and that teardown only half-runs (source).

Confirm the cancel follows a preset switch in DeepSeek Harness

All three conditions must hold: tools worked before the switch, every call after it is cancelled, and the turn still reports completed. If one is missing, leave the DSH plugin configuration alone.

  1. Find the preset-change event in the session log. Expected: every tool/call after it pairs with an AbortError.
  2. Look for evidence that a tool body started, such as file content or command output. Expected: none at all.
  3. Confirm the profile mounts auto-review and the preset is auto. Expected: the plugin appears in the list and the shield shows auto.
  4. Compare with calls before the switch. Expected: earlier results are complete, failures cluster after the switch.
  5. Record the gap between the switch and the first failure. Expected: nearly zero.
SignalThis faultTool timeoutUser abort
Tool body eventabsentpresentmay be present
Turn statecompletedusually failedaborted
Triggerafter a preset switchduring executionmanual stop

In the discussion's user scan, one sample accumulated 47 of these errors across five sessions, all after a preset change or a plugin reconfiguration (#10041).

Why the DeepSeek Harness disposal only half-runs

disposal sets accepting to false before it repairs sessions, the repair sweep throws, and the throw skips every cleanup that would remove the gate.

  1. The first statement in disposal sets accepting = false. Expected: the gate stops accepting reviews.
  2. Disposal then walks active sessions to move their preset from auto back to danger-full-access. Expected: this path reads sessionProjections.
  3. During teardown the fiber is unloading, so that read throws inactive context. Expected: the sweep aborts.
  4. Disposers run on a promise chain; after the sweep rejects, stopContribution and stopListener never run. Expected: the gate stays installed.
  5. The preset still registers auto, the gate is still there, and accepting is false. Expected: every later tool call gets cancel.

Registration order is stopListener, stopContribution, then sweep, so reverse execution runs the sweep first. A cleanup that can throw sits ahead of the cleanup that removes the gate. Ending the turn does not help either: the bad state lives on the plugin, and a turn is only an execution unit.

A separate sample shows some cancels after a full review round trip, so more than one path reaches the bad state. A session that still resolves to auto has only one exit.

Path 1: return to a fixed preset in DeepSeek Harness

This is the fastest recovery and should come first: the gate's first check passes as soon as the session no longer resolves to auto.

  1. Run /permission workspace-write or another fixed preset in the input box. Expected: the shield shows the fixed preset.
  2. Before ending the turn, call a read-only tool such as reading a known file. Expected: it returns content and does not abort.
  3. End the turn normally. Expected: no new cancels are appended.
  4. If you still want auto, switch only after the next turn starts. Expected: the first low-risk tool runs after a review round trip.
  5. Note the time of the switch. Expected: a future reproduction can be matched against it.
  6. Call a write tool as well. Expected: it follows the fixed preset instead of being cancelled.
  7. Check the shield. Expected: it stays on the fixed preset and does not jump back to auto.

The cost is losing auto review for a while. That is fine when you need to keep working, but it is not a repair.

Path 2: restart DeepSeek Harness or open a new session

A restart rebuilds the disposal chain and a new session avoids the half-removed gate; both work, and neither fixes the cause.

  1. Quit DSH fully, including tray and background processes. Expected: no DSH process remains.
  2. Start DSH and create a new session rather than reopening the old one. Expected: permissions start from defaults.
  3. Run a minimal tool, such as listing a directory. Expected: normal output with no cancel.
  4. If you need the old context, carry file paths and conclusions into the new session. Expected: work continues without the broken turn.
  5. Watch for ten minutes. Expected: no cancel returns.
  6. Call one read-only tool in the old session. Expected: if it still cancels, the bad gate was persisted.
  7. Compare the two sessions. Expected: the new one is clean, the old one keeps the residue.

If you reload plugins or switch presets often, this path only buys time. The next reconfiguration can break the gate again.

Path 3: fix the disposal order in DeepSeek Harness

Run the throwing sweep last, tolerate failures per session, and return a deny with a reason instead of a silent cancel when the gate is closed.

  1. Move the sweep's yield before stopListener and stopContribution in registration order. Expected: reverse execution removes the gate first.
  2. Wrap each session in try/catch inside the sweep, logging and continuing when a projection read fails. Expected: one bad session no longer abandons the rest.
  3. Change the gate's accepting === false result from cancel to a deny with a reason. Expected: the user sees "auto-review unavailable".
  4. Add a regression that injects a projection failure into the sweep. Expected: the gate is still removed and later calls receive the deny reason.
  5. Add an ordering test that rejects mid-disposal. Expected: the remaining disposers still run.
  6. Attach the 47-error sample distribution to the pull request. Expected: maintainers can judge the blast radius.

The ordering test matters more than the feature test: this defect only appears when one step throws, and the happy path never exercises it.

Do not stop at wrapping the sweep in try/catch. If the gate is still removed last, a future throwing step reintroduces the same half-torn state.

Reproduce and set bounds for DeepSeek Harness

Reproduce only with auto-review mounted and after a turn has started; without a running turn, the sweep has nothing to repair and the bug will not appear.

  1. Create a session with workspace-write and send a request that triggers two tool calls. Expected: both run.
  2. Switch to /permission auto after the first tool finishes and before the second starts. Expected: later calls abort.
  3. Switch back to workspace-write and call another tool. Expected: execution resumes.
  4. Save the log lines around the switch. Expected: one disposal throw is visible.
  5. Check the turn state. Expected: completed, even though no tool body ran.
  6. Count the cancels. Expected: one per tool call attempted after the switch.
  7. Run another turn under the fixed preset. Expected: zero cancels as a control.

Collect evidence on only three points: where the cancel starts, whether any tool body events exist, and whether a disposal throw sits near the switch. Four limits apply: do not toggle presets to experiment, disabling auto-review stops the bleeding but is a workaround, a completed turn is not a success so rerun steps that depended on tool side effects, and no official fixed version is named in the discussion. For the related startup deadlock, see permission auto deadlock; for the generic missing-service diagnosis, see sessionProjections inactive context.

FAQ

Why do all DeepSeek Harness tools report ABORTED_BEFORE_DISPATCH after switching to /permission auto?

The auto-review gate in DeepSeek Harness returns cancel; the tools never fail. A plugin reconfiguration tears the gate down halfway, so it stays installed but stops accepting reviews and cancels every session still resolving to auto.

Why does switching back to workspace-write restore DeepSeek Harness tools, while ending the turn does not?

The DeepSeek Harness gate first checks whether the preset equals auto. The broken gate only releases when the session stops resolving to auto, and ending a turn does not change the preset, so the cancel carries over.

After a restart DeepSeek Harness looks fine, then cancels again. Is it still broken?

A restart only lets this teardown finish; it does not repair the DeepSeek Harness ordering defect. Any later plugin reconfiguration with an auto session running reproduces the half-torn state.

How do I confirm from the log that a DeepSeek Harness gate is cancelling rather than a timeout?

Compare tool/call with tool/result in DeepSeek Harness. This case shows only AbortError with code ABORTED_BEFORE_DISPATCH, no tool body event and no timeout field, plus a disposal throw near the preset switch.

Related Terms

ABORTED_BEFORE_DISPATCH
ABORTED_BEFORE_DISPATCH is the error code DeepSeek Harness returns when a tool call is rejected before dispatch, paired with AbortError. It means the tool body never started, unlike an interruption during execution.— https://github.com/deepseek-ai/deepseek-harness/discussions/10041
auto-review
auto-review is DeepSeek Harness's experimental automatic review integration, evaluating each tool call on the tools/pre-execute hook and returning allow, deny, ask, or cancel. It only acts while the permission preset is auto.— https://github.com/deepseek-ai/deepseek-harness/discussions/10041
disposer chain
The disposer chain is the set of cleanup functions a Cordis fiber runs in reverse registration order on unload, implemented as a promise chain. Once one step rejects, the later disposers never run.— https://github.com/deepseek-ai/deepseek-harness/discussions/10041

Sources