DSH Long Sessions: Load Earlier and Trajectory Failures

Author
DeepSeekAgent.io Editorial Team
Published
Updated

DeepSeek Harness pages older events into the browser instead of loading an entire long Session at once. A DSH Desktop 0.2.1-rc.3 community reproduction exposes a stable failure chain: the first Load Earlier succeeds, the second stops Chat from prepending history, and Trajectory no longer opens until the page is reloaded.

The server page request still returns HTTP 200. The failure occurs when the client materializes historical events into Chat targets, so transport success does not prove that the page accepted the history.

Reproduction boundary

The affected Session has about 122 turns, roughly 13,000 durable events, several compactions, and seeded or inherited history. The same data reproduces in a fresh Chromium/Playwright client, which rules out an Electron-only defect.

After the second page, the console reports:

conversation Definition "system-message" withdrew materialized target "chat";
return the same key with hidden visibility instead

The event-feed subscriber then stops processing. Chat receives no more prepended history, and Trajectory cannot consume a consistent materialized state. Reloading rebuilds the client state and temporarily restores both features.

Where the failure occurs

The important path resembles buildTargetUpserts: a node previously produced a Chat target under a stable key, but its builder returns null after an older page is added. The runtime treats this as withdrawal of a materialized target and throws an invariant error.

A system-message builder can legitimately produce no visible node under a different append, replacement, or windowing context. Strict withdrawal checks are useful for live appends. During historical prepend, however, a target may simply be outside the current visible window. Destroying its identity breaks the full subscription.

Why Chat and Trajectory fail together

Chat and Trajectory look like separate views, but both depend on the Session event stream and its client materialization. Once pagination crashes the subscriber, Chat cannot construct older history and Trajectory cannot obtain a coherent snapshot. Treating these as two unrelated UI bugs would miss their shared boundary.

A useful trace records:

  • cursor, event count, and HTTP status for /api/session/page;
  • first and last event IDs before and after each load;
  • the Definition, target key, and visibility that trigger the error;
  • whether Chat and Trajectory share the same failed subscriber.

Repair direction

The robust solution has three parts:

  1. return the same target key with hidden visibility when it should temporarily disappear, rather than null;
  2. allow historical prepend to move a node outside the current window without withdrawing its identity;
  3. add a cross-page system-message regression fixture covering second and third pages, compaction boundaries, and inherited history.

Tests must assert more than HTTP 200. After the second and third loads, Chat count should grow, Trajectory should still open, and event order should match before and after a reload.

Current recovery

Reload the page to rebuild a client that already entered the failed state. If Trajectory is needed, open it before triggering the second Load Earlier. A new Session avoids expanding the broken view but does not recover old history.

Use long-session compaction and tool-result pruning to control context growth. If the Session list itself disappears or Workspace records diverge, follow the Session list recovery guide. Pagination, model-context compaction, and the Session Registry are separate layers.

References