DeepSeek Harness auto-review cancels every tool: config fix

TroubleshootingPublished 2026-10-30Author: DeepSeek Plugin Market
DeepSeek HarnessDSHauto-reviewpermission presetOpenCodetemperaturetool call
DeepSeek Harness Auto review cancels every tool call. Three reviewer faults: missing sessionId, hardcoded temperature 0, and technical failures mapped to deny.

"After switching to Auto review, even a no-argument read-only call like list_agents {} gets blocked" — when the call being denied contains no risk at all, the problem is almost never the risk policy but the reviewer itself. On one machine the community counted 15 sessions and 55 genuine review failures, including 5 calls denied within 24 seconds of running /permission auto (#10954). This article uses one comparison table to separate three fault types, then handles each in turn.

DeepSeek Harness: First, separate three "looks like permissions, actually reviewer config" faults

Judging the three faults needs only two things: the error code in the message, and whether the denied call had arguments. An error code points at the review request itself; a denied no-argument call means the review stage is broken.

TypeTypical messageTriggerRoot causeHandling
1. Missing session identity400 MissingSessionIDsession routed through OpenCode GoclassifyRisk() passes no sessionIdSwitch to a non-Auto preset, or pin the header on the route
2. Sampling parameter hardcodedinvalid temperature: only 1 is allowedmodel only accepts temperature=1request hardcodes temperature: 0Install the temperature guard plugin
3. Technical failure treated as denialAuto review of tool … failedany transport/quota/format failurefailed() returns kind: 'deny'Switch permission preset to bypass, wait for upstream policy change

Keep the order fixed: check the error code first → then the session route → finally whether every tool fails.

DSH plugin: Type 1: the review request carries no sessionId

OpenCode Go requires x-opencode-session on every inference request, but the review request passes no sessionId, so the provider never adds the header and every review gets a 400 before it reaches the model.

  1. Read the error: auto-review: reviewer ended with error INVALID_REQUEST: 400: {"type":"MissingSessionID", ...}.
  2. Confirm the session model uses the opencode-go route (the community case was opencode-go/deepseek-v4.1-flash).
  3. Verify the dependency directly: POST to the same endpoint without x-opencode-session returns 400, and with any string returns 200.
  4. Understand the chain: pi-ai's withOpenCodeSessionHeader() injects the header only when options.sessionId exists, and classifyRisk() assembles GenerateOptions without that field.
  5. Compare other auxiliary calls: the main loop, compaction (compaction-basic), and session titles all pass sessionId; only auto-review misses it.
  6. Current state: the community checked master and classifyRisk still has not added the line, so this is not "upgrade and it goes away".
  7. Workaround: switch the permission preset to a non-Auto one such as never, or pin a fixed headers.x-opencode-session in that route's config — at the cost of losing per-session routing.

DeepSeek Harness: Type 2: hardcoded temperature: 0

The review request deep-freezes temperature: 0 and hands it to ctx.llm.stream(); a model that only accepts 1 returns 400, and the failed review cancels every tool call before it runs.

  1. Read the error: auto-review: reviewer ended with error INVALID_REQUEST: 400: {"message":"invalid temperature: only 1 is allowed for this model", ...}.
  2. Confirm the session model belongs to the "only accepts temperature=1" class (the community example was a Kimi Code model).
  3. Understand the location: auto-review/src/index.ts hardcodes temperature: 0 when building options, and the serialization layer forwards any field that exists; OpenAI-compatible routes have no capability gate.
  4. Install the community plugin: dsh plugin --profile <profile> add github:argszero/dsh-auto-review-temperature-guard#v0.1.0.
  5. Add a mount entry in the profile named @argszero/dsh-auto-review-temperature-guard; with no parameter it omits temperature and lets the route default apply, and with one it sends your value.
  6. Verify: review requests no longer carry 0 and tool calls resume; non-review requests must pass through untouched, which is one of the plugin's own assertions.

The plugin identifies review requests by whether system starts with REVIEW_POLICY; ordinary turns have system undefined, so chat requests are not touched. Its boundary is explicit: if it cannot match, it silently does nothing, which is fail-open.

DSH Plugin: Type 3: technical failures treated as denial

On transport errors, timeouts, quota limits, or malformed output the reviewer uniformly returns kind: 'deny', and this path runs before await next(), so human approval never gets a chance to step in.

  1. Distinguish by wording: Auto review rejected tool … is a real judgment followed by human approval; Auto review of tool … failed is a reviewer failure that ends the call immediately.
  2. Count with that prefix; the community verified it does not mix with the rejection wording.
  3. Read the code: the failed() comment says "as a separate error rather than a denial", yet the returned kind is still 'deny'; the difference survives only as AUTO_REVIEW_FAILED_ERROR_NAME inside info.
  4. A third path already exists next door: askUser() (kind: 'ask'). The community suggests downgrading technical failures to "needs human confirmation", made configurable with ask as the default.
  5. Two aggravating factors: parseDecision runs JSON.parse on the raw text with no fence stripping, no balanced-bracket extraction, and no one-shot format-repair retry; and when schemas.length !== 1 it throws a missing-schema error, which MCP reconnects and their tool-set drift can trigger.
  6. Workaround: switch to danger-full-access or workspace-write to bypass the reviewer, or move to a route with no format violations — but this is mitigation only; the safety layer's reliability should not depend on which chat model you picked.

DeepSeek Harness: Four steps to confirm "the reviewer is broken" rather than "the policy is too strict"

Start with one control experiment: same tool, same command, with Auto switched off. If it passes without Auto, the block came from the review stage, not the command.

  1. Run /permission in the session and switch to never or workspace-write.
  2. Rerun the command that was just denied. If it passes, note the conclusion.
  3. Switch back to auto and run a no-argument read-only tool, such as listing files or agents.
  4. If the no-argument call is also denied, declare it a reviewer fault; only denials of commands with write or network arguments might be genuine risk judgments.

The value of these four steps is elimination: no source reading, no packet capture, and one pass separates "policy problem" from "reviewer problem".

DSH plugin: Why all three point at the same design problem

The reviewer reuses the session's own route and the package has no reviewer-model option, so the safety gate's reliability is tied to the chat model.

  1. Review requests take provider and model from the latest request/header, so switching models means switching reviewers.
  2. That is why "it works after changing models" is not a coincidence but structural.
  3. The long-term shape the community suggests is configuration: reviewer provider/model, maximum retries, and a per-review timeout.
  4. Until then, the fastest recovery for any of the three is switching the permission preset, rescuing the session, and only then investigating.

Cautions

Read the error prefix before changing any permission setting.

  1. Do not read "every tool is denied" as "the model sees risk". When no-argument read-only calls are denied, suspect the reviewer first.
  2. Do not treat Auto review of tool … failed as a model rejection. The prefixes differ and so does the handling.
  3. Pin the version when installing the plugin. The latest tag of experimental-auto-review once pointed at an older build, and not pinning may reproduce other problems.
  4. The plugin is mitigation, not a fix. The hardcoded 0 and the missing line are still in the source.
  5. Record the error code and the session route. Together they are the entire information needed to tell the three faults apart; missing either leaves you guessing.

If your error contains neither MissingSessionID nor invalid temperature, it is most likely type 3 — search the session log for AUTO_REVIEW_FAILED to confirm.See DeepSeek Harness aborts tool calls before dispatch for the related case.

FAQ

After enabling Auto review in DeepSeek Harness every tool is cancelled with 400 MissingSessionID — how do I fix it?

Auto review in DeepSeek Harness fails with MissingSessionID because the review request carries no sessionId. pi-ai's opencode-go provider adds the x-opencode-session header only when it receives options.sessionId, and classifyRisk() does not pass one when assembling GenerateOptions. The community checked master and the line is still missing, so switch to a non-Auto preset or pin the header on the route.

Auto review in DeepSeek Harness reports invalid temperature: only 1 is allowed for this model — is the model incompatible?

No, the model is not incompatible; the DeepSeek Harness reviewer hardcodes temperature: 0. auto-review/src/index.ts sets 0 and deep-freezes it when building the request, and models that only accept 1 return 400. The community plugin dsh-auto-review-temperature-guard can omit it or set a specific value.

Why does a DeepSeek Harness reviewer technical failure deny the call outright instead of asking a human?

DeepSeek Harness denies the call outright because the kind returned by failed() is still 'deny'. The comment says it should be treated as a separate error rather than a denial, but the permission layer only looks at kind; askUser() (kind: 'ask') already exists next door as a fallback to human confirmation, and it is not used.

How do I quickly tell a reviewer configuration fault in DeepSeek Harness from a model genuinely judging the call risky?

Two message prefixes separate the cases in DeepSeek Harness: Auto review rejected tool … is a real rejection and goes to human approval, while Auto review of tool … failed means the reviewer itself failed and the call ends immediately. When the latter appears on a no-argument read-only call, risk is almost certainly not involved.

Why does the same Auto preset work fine in DeepSeek Harness after switching models?

The same Auto preset can behave differently after a model switch because DeepSeek Harness reuses the session's own request/header route for the reviewer, and the package has no reviewer-model override. The safety layer's reliability is tied to the chat model: move to a model that accepts temperature 1 and has a session route, and both kinds of 400 disappear.

Related Terms

auto-review
auto-review is an experimental DeepSeek Harness permission preset that calls a model once to assess risk before a tool executes. A failed assessment denies the call, and the current implementation also denies when the reviewer itself fails, making it fail-closed.— https://github.com/deepseek-ai/deepseek-harness/discussions/10954
classifyRisk
classifyRisk is the function in auto-review that assembles the review request, taking provider and model from the session's latest request/header. The community check found it passes neither a sessionId nor anything but a fixed temperature of 0.— https://github.com/deepseek-ai/deepseek-harness/discussions/10643
x-opencode-session
x-opencode-session is the request header OpenCode Go requires for per-session routing attribution. pi-ai's provider adds it only when the caller supplies a sessionId, and a missing header returns 400 MissingSessionID.— https://github.com/deepseek-ai/deepseek-harness/discussions/10643
fail-closed
fail-closed is a security-gate policy of denying rather than allowing when the gate itself malfunctions. auto-review is fail-closed, but it maps 'reviewer unavailable' and 'reviewer judged this dangerous' to the same deny result, leaving users unable to tell them apart.— https://github.com/deepseek-ai/deepseek-harness/discussions/10954

Sources