DeepSeek Harness: update_goal failures, stale revision

TroubleshootingPublished 2026-10-17Author: DeepSeek Plugin Market
DeepSeek Harnessgoal mechanismupdate_goalmax_goal_roundsstale revisionsubagentautonomous rounds
DeepSeek Harness goal bugs: update_goal rejects edit-only fields, a stale revision loops forever, and goal rounds nag the main agent waiting on subagents.

DeepSeek Harness (DSH)'s goal mechanism is an "autonomous rounds" chain, and when it breaks it is not a crash but idling: when the model completes a goal it carries along parameters that apply only to editing, so update_goal reports objective and max_goal_rounds are valid only with action edit every time; after the revision expires the model retries forever with the old value, always hitting stale goal ref; and while the main agent is plainly waiting for a subagent, goal keeps nagging it, even pushing it to cancel the in-flight subagent. These three symptoms belong to three different pieces of judgement logic: asymmetric parameter validation (a text empty string is treated as not provided, a round value fails as soon as it is non-zero), version comparison with CAS semantics (a wrong id and an expired revision share one error code), and a drivability check that looks only at idle, not why it is idle (during a continuable subagent, the parent genuinely "has no visible task") (#9566, #8955, #9429).

DSH plugin asymmetric parameter validation: don't carry edit-only fields when completing a goal

The one-line conclusion: the validation uses two standards — text parameters treat an empty string as "not provided" and let it pass, while round parameters fail as soon as they are non-zero; when the model writes back the round cap returned by get_goal as-is, it hits the error 100% of the time. The error text is objective and max_goal_rounds are valid only with action edit (#9566).

DSH plugin criterion: why it is "almost certain to hit"

Per the reporter's observation and another user's session statistics (magnitude given in the thread: 38 failures out of 64 calls across 123 sessions, with 14/14 sessions failing at least once; the 26 successes were all max_goal_rounds: 0) (#9566):

  1. When completing a goal, the model tends to "fill in every field it knows", especially the round cap it just got from get_goal;
  2. The validation for the round field only judges "non-zero fails", so writing a legal value back as-is becomes the source of the error instead;
  3. The error does not give the correct form, so the model cannot self-correct from it and retries repeatedly (#9566).

DSH plugin four steps to handle it

  1. Confirm the criterion: the error text alone is enough; if switching to max_goal_rounds: 0 or simply dropping the field succeeds, this is the case (#9566).
  2. Add a project-level prompt rule (currently the most effective approach): require the model not to carry objective and max_goal_rounds in non-edit actions; set the round cap only in edit actions (#9566).
  3. Verify: rerun the same completion action, expecting success in one try with no more of that error (#9566).
  4. Upstream direction: have non-edit actions ignore these two fields, or change the error to "give the correct form" — the thread states both are fix directions (#9566).

DSH plugin stale goal ref: this is a CAS comparison, not "the goal does not exist"

The one-line conclusion: the id and revision in the error must match exactly to be accepted; a wrong id and an expired revision share the same error code, so you cannot tell which it is from the error itself — and the correct self-healing path is "read the current value from the error and resend it". The symptom is update_goal hitting stale goal ref "…" revision N; current is "…" revision M 100% of the time, with the model retrying forever with the old value without self-healing (#8955).

DSH plugin mechanism: two design defects compounded

Per the community's line-by-line source review (#8955):

  1. A compare, not a lookup: the pre-update check is a comparison rather than a lookup, so a wrong id and an expired revision fall to the same error code GOAL_STALE_REVISION;
  2. max_goal_rounds: 0 is silently treated as "not passed": this makes the error point at a field unrelated to the real cause, misleading the model further.

DSH plugin five steps to handle it

  1. Confirm the criterion: the error contains two revisions (submitted vs current); if the model submits the same old value every time, this is the case (#8955).
  2. Teach the model to copy the current value and self-heal: read current is "…" revision M out of the error and resend it verbatim once, which succeeds — this is the shortest path (#8955).
  3. Add a project-level hard rule: call get_goal before each update to get the exact id and revision, then change it; writing it into the rules is more reliable than trusting the model (#8955).
  4. A middleware approach: the thread gives a prototype — use a post-execute hook to rewrite this error into the next action (returning with block), turning the "error" into a "self-healing instruction" (#8955).
  5. Verify: rerun the multi-round updates for the same goal, expecting no more consecutive staleness (#8955).

DSH plugin mindless nagging: the check looks only at idle, not why it is idle

The one-line conclusion: the drivability check judges only "is the main agent idle", not "is it idle because it dispatched work"; while a continuable subagent runs, the main agent is idle throughout and has no task entry visible to the parent, so it is judged "drivable" and nagged continuously — in severe cases forcing the main agent to cancel the in-flight subagent. (#9429) If the subagent being nagged about is one dispatched after Agent Teams is mounted, control and reclamation run into the separate "tools replaced by the Team build, addressed by roster name" family — see DeepSeek Harness: duplicate list_agents, stuck subagents.

DSH plugin mechanism and the difference between three dispatch modes

Per the community's line-by-line source review: the readyToDrive predicate judges only agent.status === 'idle'; and a "continuable" subagent produces no task entry visible to the parent while it runs (the thread compares another implementation: the correct approach should wait for the subagent too) (#9429).

  1. Foreground one-shot: the parent can see "a task is running" and is not misjudged as idle;
  2. Background one-shot: it also has a visible task;
  3. Continuable form: no visible task — this is the exposure point (#9429).

DSH plugins five steps to handle it

  1. Confirm the criterion: goal rounds keep producing nagging while waiting for a subagent, meaningless content is stuffed into the context, and actions like "suggest canceling the in-flight subagent" even appear (#9429).
  2. Workaround one (when continuation is not needed): change the subagent to a one-shot dispatch, so the parent can see the task running and the nagging naturally decreases (#9429).
  3. Workaround two (when the continuation ability must be kept): install the community guard plugin @argszero/cordis-plugin-goal-progress-guard, which fixes the task invocation contract and uses subagent start/end events to maintain an in-flight count (#9429):
bash
npm i @argszero/cordis-plugin-goal-progress-guard
  1. Verify: run the "dispatch subagent + wait" goal round again, expecting no more nagging or cancellation suggestions (#9429).
  2. Upstream fix point: add the predicate "is it idle because it dispatched work" to the drivability check (#9429).

DSH plugin troubleshooting notes

Goal-style "idling" problems have a common trait: the error text often points at the wrong field (stale points at the revision, valid only with action edit points at the rounds), so think from "why are the values out of sync", not from the literal error. Eight points:

  1. stale is a CAS comparison failure, not "the goal is gone" (#8955).
  2. Copying the current value out of the error is the fastest self-healing: current is … is the correct value to submit (#8955).
  3. Write "fetch then change" as a hard rule, more reliable than relying on the model's memory (#8955).
  4. max_goal_rounds: 0 is treated as not passed, which manufactures an error unrelated to the real cause (#8955).
  5. Do not carry round parameters in non-edit actions: the shortest path to sidestep the asymmetric validation (#9566).
  6. An error that cannot self-correct is a design gap: when you see "the model retrying the same action repeatedly", first suspect that the error is missing the correct form (#9566).
  7. For nagging problems, look at the dispatch mode first: the continuable form is the exposure point (#9429).
  8. State the fix status honestly: all three are unfixed in the version discussed; normalizing empty-string/zero values, giving the correct form in the error, and adding a predicate to the drivability check are all core-side changes, so the user side can only rely on prompt rules and community plugins.

Goal-style autonomous-round problems often require confirming the "plugins and config" layer first when troubleshooting. Instead of typing commands everywhere to infer it, use a visual marketplace like DSH Plugin Hub: the installed list, install/uninstall history, and system logs sit in one panel, so you can see the environment clearly before acting.

Installed Plugins

Source: Discussion #9566, Discussion #8955, Discussion #9429.

FAQ

In DeepSeek Harness, update_goal keeps reporting objective and max_goal_rounds are valid only with action edit, but I only want to mark it complete. What do I do?

This comes from an unclear DeepSeek Harness placeholder-parameter convention. When marking complete, the model casually carries along parameters that apply only to edit (for example, writing back the round cap returned by get_goal as-is), and the validation is insufficiently symmetric: text parameters treat an empty string as not provided and let it pass, while round parameters fail as soon as they are non-zero. In practice, first tell the model not to carry these two fields in non-edit actions; the long-term fix is to have non-edit actions ignore them, or to give the correct form in the error.

In DeepSeek Harness, update_goal keeps reporting stale goal ref plus a revision number, and the model retries forever with the old value. How do I make it self-heal?

In DeepSeek Harness, this is a comparison, not a lookup: the id and revision in the error are accepted only when they match exactly, and a wrong id and an expired revision share the same error code, so you cannot tell which it is from the error itself. A workable self-healing path is to read the current value (current revision) from the error and resend it verbatim, or to call get_goal before each update to get the exact id and revision and then change it; writing this into a project-level rule is more reliable than trusting the model.

In DeepSeek Harness, the goal rounds keep nagging while I wait for a subagent, even demanding that I cancel the in-flight subagent. Is there a way out?

In DeepSeek Harness, this is because the drive check looks only at whether the main agent is idle, not why it is idle. While a continuable subagent runs, the main agent is idle throughout and has no visible task, so it is woken repeatedly. The workaround is to use a community guard plugin that counts in-flight subagents; the upstream fix is to add the predicate 'is it idle because it dispatched work' to the drive check.

In DeepSeek Harness, should subagents started in a goal round be switched to foreground execution to avoid the nagging?

In DeepSeek Harness, the three dispatch modes are affected to different degrees: foreground one-shot and background one-shot are both observed correctly, and only the continuable form exposes a gap on 'is there a visible task', which is why it is the easiest to misjudge as the main agent being idle. If the task does not require later continuation, switching to a one-shot form noticeably reduces nagging; if the continuation ability must be kept, use the guard plugin as a backstop.

In DeepSeek Harness, is it useful to write the update_goal error into a prompt rule?

In DeepSeek Harness, yes, and it is currently the most stable approach. Because both failures come from 'the value in the model's hand being out of sync with the current value', a project-level hard rule requiring 'fetch the current value before updating, and do not carry round parameters in non-edit actions' sidesteps it directly without depending on an upstream fix. The cost is one extra read call per round.

Related Terms

update_goal
update_goal is the tool in DeepSeek Harness that updates goal state, supporting actions such as editing the goal content and marking the goal complete. Different actions accept different fields, and carrying edit-only fields in a non-edit action is rejected by validation.— https://github.com/deepseek-ai/deepseek-harness/discussions/9566
stale goal ref
stale goal ref is the error returned when a goal update is rejected, meaning the submitted goal reference or revision number does not match the current value. It is essentially a comparison failure (CAS semantics), not 'the goal does not exist', so the fix is to fetch the current value and resend.— https://github.com/deepseek-ai/deepseek-harness/discussions/8955
continuable subagent
A continuable subagent is a subagent form that allows the parent agent to interact with it again later. While it runs it produces no task entry visible to the parent, so in the logic that 'judges drivability by whether [the agent] is idle', the parent appears to have nothing to do.— https://github.com/deepseek-ai/deepseek-harness/discussions/9429
goal-round-driver
goal-round-driver is the component in DeepSeek Harness that advances a goal across autonomous rounds, deciding when to wake the main agent via a drivability check. The current check looks only at whether the main agent is idle, and does not consider 'whether it is idle because it dispatched work'.— https://github.com/deepseek-ai/deepseek-harness/discussions/9429

Sources