DeepSeek Harness fork replay fails on an open step seed

TroubleshootingPublished 2026-10-20Author: DeepSeek Plugin Market
DeepSeek HarnessDSHforkseedTokenMeterstep replay
Forking a DeepSeek Harness session mid-step copies an unclosed step into the child seed, so TokenMeter replay rejects step/start and the child cannot open.

Fork a session while its parent is mid-step and the child is created successfully, but the first replay fails with step/start at seq 2600 arrived before turn 8/step 1 ended. The child's log is not corrupt: the fork cut landed inside a step, so the parent had not written turn/step/end while the seed already carried the next step/start. The DeepSeek Harness (DSH) replay checks ordering strictly and rejects the pair (source).

Read the error and confirm an open seed in DeepSeek Harness

Only a forked child that fails while its parent opens normally, with the error pinned to a specific seq and step, points at an unclosed seed; a parent that also fails is session corruption.

  1. Read the error for step/start, arrived before, and turn X/step Y ended together. Expected: all three appear.
  2. Find the matching step/start near the start of the child log and look for the previous step's end. Expected: the start is present and the end is missing.
  3. Fork an earlier turn that has already finished. Expected: the new child replays cleanly, ruling out file damage.
  4. Open the parent and continue it. Expected: the parent is unaffected.
  5. Record the seq named in the error. Expected: it matches the position in the child log.
SymptomOpen seedCorrupt session
Parentopens normallymay fail to open
Childreplay order errorfails at load
New forkworksstill fails

In the discussion's source review, buildForkSeed in core/session/src/fork.ts:21-29 reuses openTurnClosers from repair.ts:53 but never enforces it; core/session/src/index.ts validates each event's shape without checking tail closure; the error is raised in token-meter/src/index.ts:268-271 (#10114).

Why a DeepSeek Harness fork cuts mid-step

fork copies whatever parent events exist at that instant, and an in-flight step has no closing event to copy.

  1. The parent is executing a step; step/start and some deltas are already logged. Expected: the event list ends open.
  2. The user triggers fork and the copy logic reads the current list. Expected: a snapshot is taken.
  3. The list ends without turn/step/end, so the seed carries the open step as-is. Expected: the intermediate state enters the child.
  4. The child appends its own step/start. Expected: two starts with no end between them.
  5. Replay checks the order. Expected: it reports an out-of-range error.

Even when the parent finishes at roughly the same moment, a race between the copy and the write can capture an unclosed snapshot. Compacted sessions are more fragile because folded events hide the closure boundary.

This is why "the parent looks idle" is not proof of safety: the copy reads the event list, not the interface.

Fix 1: fork DeepSeek Harness only after the step finishes

Without code changes, waiting for the current turn to close is the most reliable way to avoid the intermediate state.

  1. Watch the parent's status bar until no tool or thinking animation runs. Expected: the session looks idle.
  2. Wait for turn/end to be written, in the log or the status bar. Expected: the closing event exists.
  3. Fork now. Expected: the child starts from a closed turn.
  4. Open the child and send one message. Expected: replay succeeds and the turn continues.
  5. If it still fails, pick an earlier completed turn as the fork point. Expected: the retry works.
  6. Wait two more seconds and fork again. Expected: the same result, so it is not a race.

This only changes your operating rhythm, and every teammate has to follow it. Batch forks forget it most often, so write "fork after the turn ends" into the runbook.

Fix 2: close the seed when DeepSeek Harness builds it

The root fix belongs in buildForkSeed: after copying, call openTurnClosers to append the missing end events, or refuse the fork outright.

  1. After copying events in fork.ts, scan the last turn and step for a matching end. Expected: the closure state is known.
  2. If either is missing, call openTurnClosers and append the generated closers. Expected: the seed ends with matching end events.
  3. If closure would change semantics, such as a tool result that has not returned, return an explicit error. Expected: the user is told to wait for the turn.
  4. Record in the seed metadata whether closers were added. Expected: diagnosis can tell a repaired seed from an original one.
  5. Add tests for three cut points: completed, in progress, and just finished. Expected: all three pass.
  6. Put the triggering seq in the pull request. Expected: maintainers can reproduce on 0.2.1-rc.2.
  7. Recheck a compacted session fork. Expected: folded boundaries are detected too.

Closing or refusing is a semantics decision. Closing is invisible to users but may expose a step that never truly completed; refusing is cleaner but requires a UI message.

Either way, the error should name the turn and step that stayed open. A bare seq forces the reader to dig through logs.

Fix 3: rebuild the DeepSeek Harness child without the bad seed

When a bad seed already exists, deleting the child and forking again from a completed turn is the least work.

  1. Back up the child directory and confirm it holds nothing unique. Expected: a safe copy exists.
  2. Delete or archive the child. Expected: the bad seed is no longer opened.
  3. Return to the parent and wait for the turn to end. Expected: the parent is idle.
  4. Fork again and confirm the new child replays. Expected: no ordering error.
  5. If the child had unique tool output, copy it into the parent first. Expected: nothing useful is lost.
  6. Check that the trash or archive still holds a copy. Expected: a mistaken delete is reversible.

Deleting is not the same as fixing. Without repair 1 or 2, the next mid-step fork produces the same bad seed.

Look for output that exists only in the child before deleting. A new fork does not bring tool results back.

Verify and set bounds for DeepSeek Harness forks

A complete fix rejects or closes a mid-step fork while leaving normal forks replayable.

  1. Start a long tool call in the parent and fork while it runs. Expected: the fork is refused or the seed is closed automatically.
  2. Wait for the turn to end, then fork. Expected: the child replays and continues normally.
  3. Inspect the child log. Expected: no isolated step/start.
  4. Rebuild statistics with TokenMeter. Expected: no out-of-range error.
  5. Fork three times in a row. Expected: all three children open.
  6. Spot-check one child when a DSH plugin drives batch forks. Expected: the seed metadata records the closure.

Check the first screen of the child, not the last message: the boundary error sits at the beginning, and later content usually looks fine. Four limits apply: never hand-edit seq, forking an in-flight session carries semantic risk, compacted sessions fork more fragilely, and no official fixed version appears in the discussion. Closing repairs structure only, so the child's token totals start with its own events. For the log-level variant, see session log seq gap repair.

FAQ

Why does a DeepSeek Harness fork child fail replay with step/start arriving before the previous step ended?

DeepSeek Harness copied an unclosed step into the seed. The previous step has no turn/step/end, so the next step/start arrives first and the replay validator treats it as out of order. The seed builder must close the step or refuse the fork.

What is a fork seed in DeepSeek Harness, and why can it contain an open step?

The fork seed is the initial event log DeepSeek Harness copies into a child, deciding which turn and step it starts from. A copy taken while a step runs has no closing event yet, so the seed ends mid-step.

How do I know a DeepSeek Harness fork failed on the seed rather than on a corrupt session file?

A DeepSeek Harness seed problem affects only forked children: the parent still opens, and the error names one seq and step pair. Check the child log for the missing end event for that step.

Can I add the missing end event to a DeepSeek Harness fork child by hand?

DeepSeek Harness events can be edited by hand, but it is risky. Order, seq continuity and every field must be exact, or you add a new replay error. Forking a completed step is safer.

Related Terms

fork seed
The fork seed is the initial event set DeepSeek Harness copies into a child session, deciding which turn and step the child starts from. It must be a closed sequence or replay fails.— https://github.com/deepseek-ai/deepseek-harness/discussions/10114
openTurnClosers
openTurnClosers is the helper DeepSeek Harness uses to turn an unclosed turn or step into a replayable closed sequence. buildForkSeed references it but does not call it unconditionally.— https://github.com/deepseek-ai/deepseek-harness/discussions/10114
TokenMeter replay
TokenMeter replay rebuilds token statistics by replaying DeepSeek Harness session events. It validates strict turn and step order and raises an error on an out-of-range step/start.— https://github.com/deepseek-ai/deepseek-harness/discussions/10114

Sources